public CreateMethodInfo ( |
||
mwi | ||
Résultat | Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMETHODINFO |
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)); }
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)); }
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)); }
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)); }
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); }
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)); }