CreateMethodInfo() public method

public CreateMethodInfo ( MethPropWithInst mwi ) : Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMETHODINFO
mwi MethPropWithInst
return Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMETHODINFO
Example #1
0
        private Expr GenerateConstructor(ExprCall expr)
        {
            Debug.Assert(expr != null);
            Debug.Assert(expr.MethWithInst.Meth().IsConstructor());
            Expr constructorInfo = ExprFactory.CreateMethodInfo(expr.MethWithInst);
            Expr args            = GenerateArgsList(expr.OptionalArguments);
            Expr Params          = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW, constructorInfo, Params));
        }
Example #2
0
        private Expr GenerateUserDefinedUnaryOperator(ExprUnaryOp expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;
            Expr       arg  = expr.Child;
            ExprCall   call = (ExprCall)expr.OptionalUserDefinedCall;

            if (call != null)
            {
                // Use the actual argument of the call; it may contain user-defined
                // conversions or be a bound lambda, and that will not be in the original
                // argument stashed away in the left child of the operator.
                arg = call.OptionalArguments;
            }
            Debug.Assert(arg != null && arg.Kind != ExpressionKind.List);
            switch (expr.Kind)
            {
            case ExpressionKind.True:
            case ExpressionKind.False:
                return(Visit(call));

            case ExpressionKind.UnaryPlus:
                pdm = PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED;
                break;

            case ExpressionKind.BitwiseNot: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; break;

            case ExpressionKind.LogicalNot: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; break;

            case ExpressionKind.DecimalNegate:
            case ExpressionKind.Negate:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED;
                break;

            case ExpressionKind.Inc:
            case ExpressionKind.Dec:
            case ExpressionKind.DecimalInc:
            case ExpressionKind.DecimalDec:
                pdm = PREDEFMETH.PM_EXPRESSION_CALL;
                break;

            default:
                throw Error.InternalCompilerError();
            }
            Expr op         = Visit(arg);
            Expr methodInfo = ExprFactory.CreateMethodInfo(expr.UserDefinedCallMethod);

            if (expr.Kind == ExpressionKind.Inc || expr.Kind == ExpressionKind.Dec ||
                expr.Kind == ExpressionKind.DecimalInc || expr.Kind == ExpressionKind.DecimalDec)
            {
                return(GenerateCall(pdm, null, methodInfo, GenerateParamsArray(op, PredefinedType.PT_EXPRESSION)));
            }
            return(GenerateCall(pdm, op, methodInfo));
        }
        private Expr GenerateUserDefinedComparisonOperator(ExprBinOp expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            switch (expr.Kind)
            {
            case ExpressionKind.StringEq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break;

            case ExpressionKind.StringNotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break;

            case ExpressionKind.DelegateEq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break;

            case ExpressionKind.DelegateNotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break;

            case ExpressionKind.Eq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break;

            case ExpressionKind.NotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break;

            case ExpressionKind.LessThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED; break;

            case ExpressionKind.LessThan: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED; break;

            case ExpressionKind.GreaterThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED; break;

            case ExpressionKind.GreaterThan: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED; break;

            default:
                throw Error.InternalCompilerError();
            }
            Expr p1 = expr.OptionalLeftChild;
            Expr p2 = expr.OptionalRightChild;

            if (expr.OptionalUserDefinedCall != null)
            {
                ExprCall udcall = (ExprCall)expr.OptionalUserDefinedCall;
                ExprList args   = (ExprList)udcall.OptionalArguments;
                Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List);

                p1 = args.OptionalElement;
                p2 = args.OptionalNextListNode;
            }
            p1 = Visit(p1);
            p2 = Visit(p2);
            FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2);
            Expr lift       = ExprFactory.CreateBoolConstant(false); // We never lift to null in C#.
            Expr methodInfo = ExprFactory.CreateMethodInfo(expr.UserDefinedCallMethod);

            return(GenerateCall(pdm, p1, p2, lift, methodInfo));
        }
Example #4
0
        private static Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr target, MethWithInst method)
        {
            // The user-defined explicit conversion from enum? to decimal or decimal? requires
            // that we convert the enum? to its nullable underlying CType.
            if (isEnumToDecimalConversion(arg.Type, CType))
            {
                // Special case: If we have enum? to decimal? then we need to emit
                // a conversion from enum? to its nullable underlying CType first.
                // This is unfortunate; we ought to reorganize how conversions are
                // represented in the Expr tree so that this is more transparent.

                // converting an enum to its underlying CType never fails, so no need to check it.
                CType underlyingType = arg.Type.StripNubs().UnderlyingEnumType;
                CType nullableType   = TypeManager.GetNullable(underlyingType);
                Expr  typeofNubEnum  = CreateTypeOf(nullableType);
                target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum);
            }

            // If the methodinfo does not return the target CType AND this is not a lifted conversion
            // from one value CType to another, then we need to wrap the whole thing in another conversion,
            // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate
            // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S))

            CType pMethodReturnType = TypeManager.SubstType(method.Meth().RetType,
                                                            method.GetType(), method.TypeArgs);
            bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.Type) && IsNullableValueType(CType)));

            Expr       typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType);
            Expr       methodInfo  = ExprFactory.CreateMethodInfo(method);
            PREDEFMETH pdmInner    = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED;
            Expr       callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo);

            if (fDontLiftReturnType)
            {
                return(callUserDefinedConversion);
            }

            PREDEFMETH pdmOuter    = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT;
            Expr       typeofOuter = CreateTypeOf(CType);

            return(GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter));
        }
Example #5
0
        protected override Expr VisitCONCAT(ExprConcat expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            if (expr.FirstArgument.Type.IsPredefType(PredefinedType.PT_STRING) && expr.SecondArgument.Type.IsPredefType(PredefinedType.PT_STRING))
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_STRING_2;
            }
            else
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_OBJECT_2;
            }
            Expr         p1         = Visit(expr.FirstArgument);
            Expr         p2         = Visit(expr.SecondArgument);
            MethodSymbol method     = GetPreDefMethod(pdm);
            Expr         methodInfo = ExprFactory.CreateMethodInfo(method, SymbolLoader.GetPredefindType(PredefinedType.PT_STRING), null);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, p1, p2, methodInfo));
        }
Example #6
0
        private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            switch (expr.Kind)
            {
            case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED; break;

            case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED; break;

            case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED; break;

            case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED; break;

            case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED; break;

            case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED; break;

            case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED; break;

            case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED; break;

            case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED; break;

            case ExpressionKind.StringEq:
            case ExpressionKind.StringNotEq:
            case ExpressionKind.DelegateEq:
            case ExpressionKind.DelegateNotEq:
            case ExpressionKind.Eq:
            case ExpressionKind.NotEq:
            case ExpressionKind.GreaterThanOrEqual:
            case ExpressionKind.GreaterThan:
            case ExpressionKind.LessThanOrEqual:
            case ExpressionKind.LessThan:
                return(GenerateUserDefinedComparisonOperator(expr));

            case ExpressionKind.DelegateSubtract:
            case ExpressionKind.Subtract:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED;
                break;

            case ExpressionKind.DelegateAdd:
            case ExpressionKind.Add:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED;
                break;

            case ExpressionKind.Multiply:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED;
                break;

            default:
                throw Error.InternalCompilerError();
            }
            Expr p1     = expr.OptionalLeftChild;
            Expr p2     = expr.OptionalRightChild;
            Expr udcall = expr.OptionalUserDefinedCall;

            if (udcall != null)
            {
                Debug.Assert(udcall.Kind == ExpressionKind.Call || udcall.Kind == ExpressionKind.UserLogicalOp);
                if (udcall is ExprCall ascall)
                {
                    ExprList args = (ExprList)ascall.OptionalArguments;
                    Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List);
                    p1 = args.OptionalElement;
                    p2 = args.OptionalNextListNode;
                }
                else
                {
                    ExprUserLogicalOp userLogOp = udcall as ExprUserLogicalOp;
                    Debug.Assert(userLogOp != null);
                    ExprList args = (ExprList)userLogOp.OperatorCall.OptionalArguments;
                    Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List);
                    p1 = ((ExprWrap)args.OptionalElement).OptionalExpression;
                    p2 = args.OptionalNextListNode;
                }
            }
            p1 = Visit(p1);
            p2 = Visit(p2);
            FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2);
            Expr methodInfo = ExprFactory.CreateMethodInfo(expr.UserDefinedCallMethod);
            Expr call       = GenerateCall(pdm, p1, p2, methodInfo);

            // Delegate add/subtract generates a call to Combine/Remove, which returns System.Delegate,
            // not the operand delegate CType.  We must cast to the delegate CType.
            if (expr.Kind == ExpressionKind.DelegateSubtract || expr.Kind == ExpressionKind.DelegateAdd)
            {
                Expr pTypeOf = CreateTypeOf(expr.Type);
                return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, pTypeOf));
            }
            return(call);
        }
Example #7
0
        protected override Expr VisitCALL(ExprCall expr)
        {
            Debug.Assert(expr != null);
            switch (expr.NullableCallLiftKind)
            {
            default:
                break;

            case NullableCallLiftKind.NullableIntermediateConversion:
            case NullableCallLiftKind.NullableConversion:
            case NullableCallLiftKind.NullableConversionConstructor:
                return(GenerateConversion(expr.OptionalArguments, expr.Type, expr.isChecked()));

            case NullableCallLiftKind.NotLiftedIntermediateConversion:
            case NullableCallLiftKind.UserDefinedConversion:
                return(GenerateUserDefinedConversion(expr.OptionalArguments, expr.Type, expr.MethWithInst));
            }

            if (expr.MethWithInst.Meth().IsConstructor())
            {
                return(GenerateConstructor(expr));
            }

            ExprMemberGroup memberGroup = expr.MemberGroup;

            if (memberGroup.IsDelegate)
            {
                return(GenerateDelegateInvoke(expr));
            }

            Expr pObject;

            if (expr.MethWithInst.Meth().isStatic || expr.MemberGroup.OptionalObject == null)
            {
                pObject = ExprFactory.CreateNull();
            }
            else
            {
                pObject = expr.MemberGroup.OptionalObject;

                // If we have, say, an int? which is the object of a call to ToString
                // then we do NOT want to generate ((object)i).ToString() because that
                // will convert a null-valued int? to a null object.  Rather what we want
                // to do is box it to a ValueType and call ValueType.ToString.
                //
                // To implement this we say that if the object of the call is an implicit boxing cast
                // then just generate the object, not the cast.  If the cast is explicit in the
                // source code then it will be an EXPLICITCAST and we will visit it normally.
                //
                // It might be better to rewrite the expression tree API so that it
                // can handle in the general case all implicit boxing conversions. Right now it
                // requires that all arguments to a call that need to be boxed be explicitly boxed.

                if (pObject != null && pObject is ExprCast cast && cast.IsBoxingCast)
                {
                    pObject = cast.Argument;
                }
                pObject = Visit(pObject);
            }
            Expr       methodInfo = ExprFactory.CreateMethodInfo(expr.MethWithInst);
            Expr       args       = GenerateArgsList(expr.OptionalArguments);
            Expr       Params     = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION);
            PREDEFMETH pdm        = PREDEFMETH.PM_EXPRESSION_CALL;

            Debug.Assert(!expr.MethWithInst.Meth().isVirtual || expr.MemberGroup.OptionalObject != null);

            return(GenerateCall(pdm, pObject, methodInfo, Params));
        }