Пример #1
0
        public UserOperatorCall(MethodGroupExpression method, Arguments args, SourceSpan span)
        {
            _method    = method;
            _arguments = args;

            Type            = ((MethodInfo)method).ReturnType;
            ExpressionClass = ExpressionClass.Value;
            Span            = span;
        }
Пример #2
0
        public override Expression DoResolve(ParseContext ec)
        {
            var typeExpression = _requestedType.ResolveAsTypeTerminal(ec, false);

            if (typeExpression == null)
            {
                return(null);
            }

            Type = _resolvedType = typeExpression.Type;

            if (Arguments == null)
            {
                var c = Constantify(_resolvedType);
                if (c != null)
                {
                    return(ReducedExpression.Create(c, this));
                }
            }

            if (TypeManager.IsGenericParameter(_resolvedType))
            {
                var gc = TypeManager.GetTypeParameterConstraints(_resolvedType);

                if ((gc == null) || (!gc.HasConstructorConstraint && !gc.IsValueType))
                {
                    ec.ReportError(
                        304,
                        string.Format(
                            "Cannot create an instance of the variable type '{0}' because it doesn't have the new() constraint.",
                            TypeManager.GetCSharpName(_resolvedType)),
                        Span);

                    return(null);
                }

                if ((_arguments != null) && (_arguments.Count != 0))
                {
                    ec.ReportError(
                        417,
                        string.Format(
                            "'{0}': cannot provide arguments when creating an instance of a variable type.",
                            TypeManager.GetCSharpName(_resolvedType)),
                        Span);

                    return(null);
                }

                ExpressionClass = ExpressionClass.Value;
                return(this);
            }

            if (_resolvedType.IsAbstract && _resolvedType.IsSealed)
            {
                ec.ReportError(
                    712,
                    string.Format(
                        "Cannot create an instance of the static class '{0}'.",
                        TypeManager.GetCSharpName(_resolvedType)),
                    Span);

                return(null);
            }

            if (_resolvedType.IsInterface || _resolvedType.IsAbstract)
            {
                ec.ReportError(
                    144,
                    string.Format(
                        "Cannot create an instance of the abstract class or interface '{0}'.",
                        TypeManager.GetCSharpName(_resolvedType)),
                    Span);

                return(null);
            }

            var isStruct = TypeManager.IsStruct(_resolvedType);

            ExpressionClass = ExpressionClass.Value;

            //
            // SRE returns a match for .ctor () on structs (the object constructor),
            // so we have to manually ignore it.
            //
            if (isStruct && (_arguments != null) && !_arguments.Any())
            {
                return(this);
            }

            // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
            var memberLookup = MemberLookupFinal(
                ec,
                _resolvedType,
                _resolvedType,
                ConstructorInfo.ConstructorName,
                MemberTypes.Constructor,
                AllBindingFlags | BindingFlags.DeclaredOnly,
                Span);

            if (_arguments != null)
            {
                _arguments.Resolve(ec);
            }

            if (memberLookup == null)
            {
                return(null);
            }

            _constructor = memberLookup as MethodGroupExpression;

            if (_constructor == null)
            {
                memberLookup.OnErrorUnexpectedKind(ec, ResolveFlags.MethodGroup, Span);
                return(null);
            }

            _constructor = _constructor.OverloadResolve(ec, ref _arguments, false, Span);

            return((_constructor == null) ? null : this);
        }
Пример #3
0
        //
        // Unary user type overload resolution
        //
        private Expression ResolveUserType(ParseContext ec, Expression expr)
        {
            Expression bestExpr = ResolveUserOperator(ec, expr);

            if (bestExpr != null)
            {
                return(bestExpr);
            }

            var predefined = _predefinedOperators[Operator];

            foreach (var t in predefined)
            {
                var operExpr = ConvertExpression.MakeExplicitConversion(ec, expr, t, expr.Span);
                if (operExpr == null)
                {
                    continue;
                }

                //
                // decimal type is predefined but has user-operators
                //
                if (operExpr.Type == TypeManager.CoreTypes.Decimal)
                {
                    operExpr = ResolveUserType(ec, operExpr);
                }
                else
                {
                    operExpr = ResolvePrimitivePredefinedType(ec, operExpr);
                }

                if (operExpr == null)
                {
                    continue;
                }

                if (bestExpr == null)
                {
                    bestExpr = operExpr;
                    continue;
                }

                int result = MethodGroupExpression.BetterTypeConversion(ec, bestExpr.Type, t);
                if (result == 0)
                {
                    ec.ReportError(
                        35,
                        string.Format(
                            "Operator '{0}' is ambiguous on an operand of type '{1}'.",
                            GetOperatorToken(Operator),
                            TypeManager.GetCSharpName(expr.Type)),
                        Span);
                    break;
                }

                if (result == 2)
                {
                    bestExpr = operExpr;
                }
            }

            if (bestExpr == null)
            {
                return(null);
            }

            //
            // HACK: Decimal user-operator is included in standard operators
            //
            if (bestExpr.Type == TypeManager.CoreTypes.Decimal)
            {
                return(bestExpr);
            }

            Operand = bestExpr;
            Type    = bestExpr.Type;

            return(this);
        }
Пример #4
0
        public override Expression DoResolve(ParseContext ec)
        {
            // Don't resolve already resolved expression
            if (ExpressionClass != ExpressionClass.Invalid)
            {
                return(this);
            }

            var resolvedTarget = Target.Resolve(ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);

            if (resolvedTarget == null)
            {
                return(null);
            }

            // Next, evaluate all the expressions in the argument list
            if (_arguments != null && !_argumentsResolved)
            {
                _arguments.Resolve(ec);
                _argumentsResolved = true;
            }

            var expressionType = resolvedTarget.Type;

            MethodGroup = resolvedTarget as MethodGroupExpression;

            if (MethodGroup == null)
            {
                if (expressionType != null && TypeManager.IsDelegateType(expressionType))
                {
                    MethodGroup = (resolvedTarget = new MemberAccessExpression
                    {
                        Left = resolvedTarget,
                        Name = "Invoke",
                        Span = Span
                    }.Resolve(ec)) as MethodGroupExpression;
                }

                var memberExpression = resolvedTarget as MemberExpression;
                if (memberExpression == null)
                {
                    resolvedTarget.OnErrorUnexpectedKind(ec, ResolveFlags.MethodGroup, Span);
                    return(null);
                }

                if (MethodGroup == null)
                {
                    MethodGroup = ec.LookupExtensionMethod(
                        memberExpression.Type,
                        memberExpression.Name,
                        Span);

                    if (MethodGroup != null)
                    {
                        ((ExtensionMethodGroupExpression)MethodGroup).ExtensionExpression = memberExpression.InstanceExpression;
                    }
                }

                if (MethodGroup == null)
                {
                    ec.ReportError(
                        1955,
                        string.Format(
                            "The member '{0}' cannot be used as method or delegate.",
                            resolvedTarget.GetSignatureForError()),
                        Span);

                    return(null);
                }
            }

            MethodGroup = DoResolveOverload(ec);

            if (MethodGroup == null)
            {
                return(null);
            }

            var method = (MethodInfo)MethodGroup;

            if (method != null)
            {
                Type = method.ReturnType;

                // TODO: this is a copy of mg.ResolveMemberAccess method
                var instanceExpression = MethodGroup.InstanceExpression;
                if (method.IsStatic)
                {
                    if (instanceExpression == null ||
                        instanceExpression is EmptyExpression ||
                        MethodGroup.IdenticalTypeName)
                    {
                        MethodGroup.InstanceExpression = null;
                    }
                    else
                    {
                        // TODO: MemberExpression.error176(ec, loc, mg.GetSignatureForError());
                        return(null);
                    }
                }
                else
                {
                    if (instanceExpression == null || instanceExpression == EmptyExpression.Null)
                    {
                        // TODO: SimpleName.Error_ObjectRefRequired(ec, loc, mg.GetSignatureForError());
                    }
                }
            }

            if (method == null)
            {
                return(null);
            }

            IsSpecialMethodInvocation(ec, method, Span);

            ExpressionClass = ExpressionClass.Value;
            return(this);
        }
Пример #5
0
 public static Delegate[] GetDelegates(IEnumerable <object> objects) => (
     from t in objects
     from m in t.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)
         where m.DeclaringType != typeof(object)
     select t is Delegate ? (Delegate)t : m.CreateDelegate(MethodGroupExpression.GetDelegateType(m), t)
     ).ToArray();
Пример #6
0
        void MakeOutputTypeInference(AST.Expression e, IType t)
        {
            // If E is an anonymous function with inferred return type  U (§7.5.2.12) and T is a delegate type or expression
            // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb.
            LambdaExpression lrr = e as LambdaExpression;

            if (lrr != null)
            {
                IMethod m = GetDelegateOrExpressionTreeSignature(t);
                if (m != null)
                {
                    IType inferredReturnType;
                    if (lrr.IsImplicitlyTyped)
                    {
                        if (m.Parameters.Count != lrr.Parameters.Count)
                        {
                            return;                             // cannot infer due to mismatched parameter lists
                        }
                        TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
                        IType[] inferredParameterTypes         = new IType[m.Parameters.Count];
                        for (int i = 0; i < inferredParameterTypes.Length; i++)
                        {
                            IType parameterType = m.Parameters[i].Type;
                            inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution);
                        }
                        inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes);
                    }
                    else
                    {
                        inferredReturnType = lrr.GetInferredReturnType(null);
                    }
                    MakeLowerBoundInference(inferredReturnType, m.ReturnType);
                    return;
                }
            }
            // Otherwise, if E is a method group and T is a delegate type or expression tree type
            // with parameter types T1…Tk and return type Tb, and overload resolution
            // of E with the types T1…Tk yields a single method with return type U, then a lower­-bound
            // inference is made from U to Tb.
            MethodGroupExpression mgrr = e as MethodGroupExpression;

            if (mgrr != null)
            {
                IMethod m = GetDelegateOrExpressionTreeSignature(t);
                if (m != null)
                {
                    Expression[] args = new Expression[m.Parameters.Count];
                    TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
                    for (int i = 0; i < args.Length; i++)
                    {
                        IParameter param         = m.Parameters[i];
                        IType      parameterType = param.Type.AcceptVisitor(substitution);
                        if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference)
                        {
                            parameterType = ((ByReferenceType)parameterType).ElementType;
                            args[i]       = new ByReferenceExpression(parameterType, param.IsOut);
                        }
                        else
                        {
                            args[i] = new Expression(parameterType);
                        }
                    }
                    var or = mgrr.PerformOverloadResolution(compilation,
                                                            args,
                                                            allowExpandingParams: false, allowOptionalParameters: false);
                    if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null)
                    {
                        IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;
                        MakeLowerBoundInference(returnType, m.ReturnType);
                    }
                }
                return;
            }
            // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
            if (IsValidType(e.Type))
            {
                MakeLowerBoundInference(e.Type, t);
            }
        }
Пример #7
0
 public ConditionalLogicalOperator(MethodGroupExpression operMethod, Arguments arguments, SourceSpan loc)
     : base(operMethod, arguments, loc)
 {
 }