/// <summary> /// Calculates the variable type and other required values for enumeration of an IEnumerable`1. /// </summary> private void detectEnumerableType(Context ctx) { var seqType = IterableExpression.Resolve(ctx); if (seqType.IsArray) { _VariableType = seqType.GetElementType(); return; } var ifaces = seqType.ResolveInterfaces(); if (seqType.IsInterface) ifaces = ifaces.Union(new[] { seqType }).ToArray(); var generic = ifaces.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); if (generic != null) _EnumeratorType = typeof(IEnumerator<>).MakeGenericType(generic.GetGenericArguments()[0]); else if (ifaces.Contains(typeof(IEnumerable))) _EnumeratorType = typeof(IEnumerator); else error(IterableExpression, CompilerMessages.TypeNotIterable, seqType); _CurrentProperty = ctx.ResolveProperty(_EnumeratorType, "Current"); _VariableType = _CurrentProperty.PropertyType; }
private void detectEnumerableType(Context ctx) { var seqType = IterableExpression.GetExpressionType(ctx); if (seqType.IsArray) { m_VariableType = seqType.GetElementType(); return; } var ifaces = GenericHelper.GetInterfaces(seqType); if(!ifaces.Any(i => i == typeof(IEnumerable) || (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))) Error(IterableExpression, CompilerMessages.TypeNotIterable, seqType); var enumerator = ctx.ResolveMethod(seqType, "GetEnumerator"); m_EnumeratorType = enumerator.ReturnType; m_CurrentProperty = ctx.ResolveProperty(m_EnumeratorType, "Current"); m_VariableType = m_CurrentProperty.PropertyType; }
/// <summary> /// Resolves the method if the expression was a member getter (obj.field or type::field). /// </summary> private void resolveGetMember(Context ctx, GetMemberNode node) { _InvocationSource = node.Expression; var type = _InvocationSource != null ? _InvocationSource.Resolve(ctx) : ctx.ResolveType(node.StaticType); checkTypeInSafeMode(ctx, type); if (node.TypeHints != null && node.TypeHints.Count > 0) _TypeHints = node.TypeHints.Select(x => ctx.ResolveType(x, true)).ToArray(); try { // resolve a normal method try { _Method = ctx.ResolveMethod( type, node.MemberName, _ArgTypes, _TypeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); if (_Method.IsStatic) _InvocationSource = null; return; } catch (KeyNotFoundException) { if (_InvocationSource == null) throw; } // resolve a callable field try { ctx.ResolveField(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } // resolve a callable property try { ctx.ResolveProperty(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } Arguments = (Arguments[0] is UnitNode) ? new List<NodeBase> {_InvocationSource} : new[] {_InvocationSource}.Union(Arguments).ToList(); var oldArgTypes = _ArgTypes; _ArgTypes = Arguments.Select(a => a.Resolve(ctx)).ToArray(); _InvocationSource = null; try { // resolve a local function that is implicitly used as an extension method _Method = ctx.ResolveMethod( ctx.MainType.TypeInfo, node.MemberName, _ArgTypes, resolver: (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); return; } catch (KeyNotFoundException) { } // resolve a declared extension method // most time-consuming operation, therefore is last checked try { if(!ctx.Options.AllowExtensionMethods) throw new KeyNotFoundException(); _Method = ctx.ResolveExtensionMethod( type, node.MemberName, oldArgTypes, _TypeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); } catch (KeyNotFoundException) { var msg = node.StaticType != null ? CompilerMessages.TypeStaticMethodNotFound : CompilerMessages.TypeMethodNotFound; error(msg, type, node.MemberName); } } catch (AmbiguousMatchException) { error(CompilerMessages.TypeMethodInvocationAmbiguous, type, node.MemberName); } }
private void resolveGetMember(Context ctx, GetMemberNode node) { m_InvocationSource = node.Expression; var type = m_InvocationSource != null ? m_InvocationSource.GetExpressionType(ctx) : ctx.ResolveType(node.StaticType); SafeModeCheckType(ctx, type); if (node.TypeHints.Any()) m_TypeHints = node.TypeHints.Select(x => x.FullSignature == "_" ? null : ctx.ResolveType(x)).ToArray(); try { // resolve a normal method try { m_Method = ctx.ResolveMethod(type, node.MemberName, m_ArgTypes, m_TypeHints); if (m_Method.IsStatic) m_InvocationSource = null; return; } catch (KeyNotFoundException) { if (m_InvocationSource == null) throw; } // resolve a callable field try { ctx.ResolveField(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } // resolve a callable field try { ctx.ResolveProperty(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } // resolve a local function that is implicitly used as an extension method // move invocation source to arguments if (Arguments[0] is UnitNode) Arguments[0] = m_InvocationSource; else Arguments.Insert(0, m_InvocationSource); var oldArgTypes = m_ArgTypes; m_ArgTypes = Arguments.Select(a => a.GetExpressionType(ctx)).ToArray(); m_InvocationSource = null; try { m_Method = ctx.ResolveMethod(ctx.MainType.TypeInfo, node.MemberName, m_ArgTypes); } catch (KeyNotFoundException) { // resolve a declared extension method // most time-consuming operation, therefore is last checked if(ctx.Options.AllowExtensionMethods) m_Method = ctx.ResolveExtensionMethod(type, node.MemberName, oldArgTypes, m_TypeHints); } } catch (AmbiguousMatchException) { Error(CompilerMessages.TypeMethodInvocationAmbiguous, type, node.MemberName); } catch (KeyNotFoundException) { var msg = node.StaticType != null ? CompilerMessages.TypeStaticMethodNotFound : CompilerMessages.TypeMethodNotFound; Error(msg, type, node.MemberName); } }
/// <summary> /// Attempts to resolve current node and sets either of the following fields: /// _Field, _Method, _Property /// /// The following fields are also set: /// _Type, _Static /// </summary> private void resolveSelf(Context ctx) { Action check = () => { if (Expression == null && !_IsStatic) error(CompilerMessages.DynamicMemberFromStaticContext, _Type, MemberName); if (_Method == null && TypeHints.Count > 0) error(CompilerMessages.TypeArgumentsForNonMethod, _Type, MemberName); }; _Type = StaticType != null ? ctx.ResolveType(StaticType) : Expression.Resolve(ctx); // special case: array length if (_Type.IsArray && MemberName == "Length") { check(); return; } // check for field try { _Field = ctx.ResolveField(_Type, MemberName); _IsStatic = _Field.IsStatic; check(); return; } catch (KeyNotFoundException) { } // check for property try { _Property = ctx.ResolveProperty(_Type, MemberName); if(!_Property.CanGet) error(CompilerMessages.PropertyNoGetter, _Type, MemberName); _IsStatic = _Property.IsStatic; check(); return; } catch (KeyNotFoundException) { } // check for event: events are only allowed at the left side of += and -= try { ctx.ResolveEvent(_Type, MemberName); error(CompilerMessages.EventAsExpr); } catch (KeyNotFoundException) { } // find method var argTypes = TypeHints.Select(t => t.FullSignature == "_" ? null : ctx.ResolveType(t)).ToArray(); var methods = ctx.ResolveMethodGroup(_Type, MemberName).Where(m => checkMethodArgs(argTypes, m)).ToArray(); if (methods.Length == 0) error(argTypes.Length == 0 ? CompilerMessages.TypeIdentifierNotFound : CompilerMessages.TypeMethodNotFound, _Type.Name, MemberName); if (methods.Length > 1) error(CompilerMessages.TypeMethodAmbiguous, _Type.Name, MemberName); _Method = methods[0]; if (_Method.ArgumentTypes.Length > 16) error(CompilerMessages.CallableTooManyArguments); _IsStatic = _Method.IsStatic; check(); }
/// <summary> /// Attempts to resolve member reference to a field or a property. /// </summary> private void resolveSelf(Context ctx) { var type = StaticType != null ? ctx.ResolveType(StaticType) : Expression.Resolve(ctx); checkTypeInSafeMode(ctx, type); // check for field try { _Field = ctx.ResolveField(type, MemberName); _IsStatic = _Field.IsStatic; if (Expression == null && !_IsStatic) error(CompilerMessages.DynamicMemberFromStaticContext, type, MemberName); } catch (KeyNotFoundException) { try { _Property = ctx.ResolveProperty(type, MemberName); if (!_Property.CanSet) error(CompilerMessages.PropertyNoSetter, MemberName, type); _IsStatic = _Property.IsStatic; if (Expression == null && !_IsStatic) error(CompilerMessages.DynamicMemberFromStaticContext, type, MemberName); } catch (KeyNotFoundException) { error(CompilerMessages.TypeSettableIdentifierNotFound, type, MemberName); } } var destType = _Field != null ? _Field.FieldType : _Property.PropertyType; ensureLambdaInferred(ctx, Value, destType); var valType = Value.Resolve(ctx); ctx.CheckTypedExpression(Value, valType, true); if (!destType.IsExtendablyAssignableFrom(valType)) error(CompilerMessages.ImplicitCastImpossible, valType, destType); }
private void resolve(Context ctx) { Action check = () => { if (Expression == null && !m_IsStatic) Error(CompilerMessages.DynamicMemberFromStaticContext, MemberName); if(m_Method == null && TypeHints.Count > 0) Error(CompilerMessages.TypeArgumentsForNonMethod, m_Type, MemberName); m_IsResolved = true; }; m_Type = StaticType != null ? ctx.ResolveType(StaticType) : Expression.GetExpressionType(ctx); // special case: array length if (m_Type.IsArray && MemberName == "Length") { check(); return; } // check for field try { m_Field = ctx.ResolveField(m_Type, MemberName); m_IsStatic = m_Field.IsStatic; check(); return; } catch (KeyNotFoundException) { } // check for property try { m_Property = ctx.ResolveProperty(m_Type, MemberName); if(!m_Property.CanGet) Error(CompilerMessages.PropertyNoGetter, m_Type, MemberName); m_IsStatic = m_Property.IsStatic; check(); return; } catch (KeyNotFoundException) { } var argTypes = TypeHints.Select(t => t.FullSignature == "_" ? null : ctx.ResolveType(t)).ToArray(); var methods = ctx.ResolveMethodGroup(m_Type, MemberName).Where(m => checkMethodArgs(ctx, argTypes, m)).ToArray(); if (methods.Length == 0) Error(argTypes.Length == 0 ? CompilerMessages.TypeIdentifierNotFound : CompilerMessages.TypeMethodNotFound, m_Type.Name, MemberName); if (methods.Length > 1) Error(CompilerMessages.TypeMethodAmbiguous, m_Type.Name, MemberName); m_Method = methods[0]; if (m_Method.ArgumentTypes.Length > 16) Error(CompilerMessages.CallableTooManyArguments); m_IsStatic = m_Method.IsStatic; check(); }
private void resolve(Context ctx) { var type = StaticType != null ? ctx.ResolveType(StaticType) : Expression.GetExpressionType(ctx); SafeModeCheckType(ctx, type); // check for field try { m_Field = ctx.ResolveField(type, MemberName); m_IsStatic = m_Field.IsStatic; if (Expression == null && !m_IsStatic) Error(CompilerMessages.DynamicMemberFromStaticContext, type, MemberName); return; } catch (KeyNotFoundException) { } try { m_Property = ctx.ResolveProperty(type, MemberName); if(!m_Property.CanSet) Error(CompilerMessages.PropertyNoSetter, MemberName, type); m_IsStatic = m_Property.IsStatic; if (Expression == null && !m_IsStatic) Error(CompilerMessages.DynamicMemberFromStaticContext, MemberName, type); } catch (KeyNotFoundException) { Error(CompilerMessages.TypeSettableIdentifierNotFound, type, MemberName); } }