<PackageReference Include="Microsoft.CSharp" Version="4.6.0-preview.19073.11" />

ExpressionTreeRewriter

using Microsoft.CSharp.RuntimeBinder.Syntax; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal sealed class ExpressionTreeRewriter : ExprVisitorBase { public static ExprBinOp Rewrite(ExprBoundLambda expr) { return new ExpressionTreeRewriter().VisitBoundLambda(expr); } protected override Expr Dispatch(Expr expr) { Expr expr2 = base.Dispatch(expr); if (expr2 == expr) throw Error.InternalCompilerError(); return expr2; } protected override Expr VisitASSIGNMENT(ExprAssignment assignment) { ExprProperty exprProperty; Expr arg; if ((exprProperty = (assignment.LHS as ExprProperty)) != null) { if (exprProperty.OptionalArguments == null) arg = Visit(exprProperty); else { Expr arg2 = Visit(exprProperty.MemberGroup.OptionalObject); Expr arg3 = ExprFactory.CreatePropertyInfo(exprProperty.PropWithTypeSlot.Prop(), exprProperty.PropWithTypeSlot.Ats); Expr arg4 = GenerateParamsArray(GenerateArgsList(exprProperty.OptionalArguments), PredefinedType.PT_EXPRESSION); arg = GenerateCall(PREDEFMETH.PM_EXPRESSION_PROPERTY, arg2, arg3, arg4); } } else arg = Visit(assignment.LHS); Expr arg5 = Visit(assignment.RHS); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ASSIGN, arg, arg5); } protected override Expr VisitMULTIGET(ExprMultiGet pExpr) { return Visit(pExpr.OptionalMulti.Left); } protected override Expr VisitMULTI(ExprMulti pExpr) { Expr arg = Visit(pExpr.Operator); Expr arg2 = Visit(pExpr.Left); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ASSIGN, arg2, arg); } private ExprBinOp VisitBoundLambda(ExprBoundLambda anonmeth) { MethodSymbol preDefMethod = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA); AggregateType delegateType = anonmeth.DelegateType; TypeArray typeArgs = TypeArray.Allocate(delegateType); AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); MethWithInst methWithInst = new MethWithInst(preDefMethod, predefindType, typeArgs); Expr first = CreateWraps(anonmeth); Expr op = Visit(anonmeth.Expression); Expr op2 = GenerateParamsArray(null, PredefinedType.PT_PARAMETEREXPRESSION); Expr arguments = ExprFactory.CreateList(op, op2); CType type = TypeManager.SubstType(methWithInst.Meth().RetType, methWithInst.GetType(), methWithInst.TypeArgs); ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, type, arguments, memberGroup, methWithInst); exprCall.PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA; return ExprFactory.CreateSequence(first, exprCall); } protected override Expr VisitCONSTANT(ExprConstant expr) { return GenerateConstant(expr); } protected override Expr VisitLOCAL(ExprLocal local) { return local.Local.wrap; } protected override Expr VisitFIELD(ExprField expr) { Expr arg = (expr.OptionalObject != null) ? Visit(expr.OptionalObject) : ExprFactory.CreateNull(); ExprFieldInfo arg2 = ExprFactory.CreateFieldInfo(expr.FieldWithType.Field(), expr.FieldWithType.GetType()); return GenerateCall(PREDEFMETH.PM_EXPRESSION_FIELD, arg, arg2); } protected override Expr VisitUSERDEFINEDCONVERSION(ExprUserDefinedConversion expr) { return GenerateUserDefinedConversion(expr, expr.Argument); } protected override Expr VisitCAST(ExprCast pExpr) { Expr argument = pExpr.Argument; if (argument.Type == pExpr.Type || SymbolLoader.IsBaseClassOfClass(argument.Type, pExpr.Type) || CConversions.FImpRefConv(argument.Type, pExpr.Type)) return Visit(argument); if (pExpr.Type != null && pExpr.Type.IsPredefType(PredefinedType.PT_G_EXPRESSION) && argument is ExprBoundLambda) return Visit(argument); Expr expr = GenerateConversion(argument, pExpr.Type, pExpr.isChecked()); if ((pExpr.Flags & EXPRFLAG.EXF_USERCALLABLE) != 0) expr.Flags |= EXPRFLAG.EXF_USERCALLABLE; return expr; } protected override Expr VisitCONCAT(ExprConcat expr) { PREDEFMETH pdm = (!expr.FirstArgument.Type.IsPredefType(PredefinedType.PT_STRING) || !expr.SecondArgument.Type.IsPredefType(PredefinedType.PT_STRING)) ? PREDEFMETH.PM_STRING_CONCAT_OBJECT_2 : PREDEFMETH.PM_STRING_CONCAT_STRING_2; Expr arg = Visit(expr.FirstArgument); Expr arg2 = Visit(expr.SecondArgument); MethodSymbol preDefMethod = GetPreDefMethod(pdm); Expr arg3 = ExprFactory.CreateMethodInfo(preDefMethod, SymbolLoader.GetPredefindType(PredefinedType.PT_STRING), null); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, arg, arg2, arg3); } protected override Expr VisitBINOP(ExprBinOp expr) { if ((SymWithType)expr.UserDefinedCallMethod != (SymWithType)null) return GenerateUserDefinedBinaryOperator(expr); return GenerateBuiltInBinaryOperator(expr); } protected override Expr VisitUNARYOP(ExprUnaryOp pExpr) { if ((SymWithType)pExpr.UserDefinedCallMethod != (SymWithType)null) return GenerateUserDefinedUnaryOperator(pExpr); return GenerateBuiltInUnaryOperator(pExpr); } protected override Expr VisitARRAYINDEX(ExprArrayIndex pExpr) { Expr arg = Visit(pExpr.Array); Expr expr = GenerateIndexList(pExpr.Index); if (expr is ExprList) { Expr arg2 = GenerateParamsArray(expr, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2, arg, arg2); } return GenerateCall(PREDEFMETH.PM_EXPRESSION_ARRAYINDEX, arg, expr); } protected override Expr VisitCALL(ExprCall expr) { switch (expr.NullableCallLiftKind) { case NullableCallLiftKind.NullableConversion: case NullableCallLiftKind.NullableConversionConstructor: case NullableCallLiftKind.NullableIntermediateConversion: return GenerateConversion(expr.OptionalArguments, expr.Type, expr.isChecked()); case NullableCallLiftKind.UserDefinedConversion: case NullableCallLiftKind.NotLiftedIntermediateConversion: return GenerateUserDefinedConversion(expr.OptionalArguments, expr.Type, expr.MethWithInst); default: { if (expr.MethWithInst.Meth().IsConstructor()) return GenerateConstructor(expr); ExprMemberGroup memberGroup = expr.MemberGroup; if (memberGroup.IsDelegate) return GenerateDelegateInvoke(expr); Expr arg; if (expr.MethWithInst.Meth().isStatic || expr.MemberGroup.OptionalObject == null) arg = ExprFactory.CreateNull(); else { arg = expr.MemberGroup.OptionalObject; ExprCast exprCast; if (arg != null && (exprCast = (arg as ExprCast)) != null && exprCast.IsBoxingCast) arg = exprCast.Argument; arg = Visit(arg); } Expr arg2 = ExprFactory.CreateMethodInfo(expr.MethWithInst); Expr args = GenerateArgsList(expr.OptionalArguments); Expr arg3 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); PREDEFMETH pdm = PREDEFMETH.PM_EXPRESSION_CALL; return GenerateCall(pdm, arg, arg2, arg3); } } } protected override Expr VisitPROP(ExprProperty expr) { Expr arg = (!expr.PropWithTypeSlot.Prop().isStatic && expr.MemberGroup.OptionalObject != null) ? Visit(expr.MemberGroup.OptionalObject) : ExprFactory.CreateNull(); Expr arg2 = ExprFactory.CreatePropertyInfo(expr.PropWithTypeSlot.Prop(), expr.PropWithTypeSlot.GetType()); if (expr.OptionalArguments != null) { Expr args = GenerateArgsList(expr.OptionalArguments); Expr arg3 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_PROPERTY, arg, arg2, arg3); } return GenerateCall(PREDEFMETH.PM_EXPRESSION_PROPERTY, arg, arg2); } protected override Expr VisitARRINIT(ExprArrayInit expr) { Expr arg = CreateTypeOf(((ArrayType)expr.Type).ElementType); Expr args = GenerateArgsList(expr.OptionalArguments); Expr arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT, arg, arg2); } protected override Expr VisitZEROINIT(ExprZeroInit expr) { return GenerateConstant(expr); } protected override Expr VisitTYPEOF(ExprTypeOf expr) { return GenerateConstant(expr); } private Expr GenerateDelegateInvoke(ExprCall expr) { ExprMemberGroup memberGroup = expr.MemberGroup; Expr optionalObject = memberGroup.OptionalObject; Expr arg = Visit(optionalObject); Expr args = GenerateArgsList(expr.OptionalArguments); Expr arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_INVOKE, arg, arg2); } private Expr GenerateBuiltInBinaryOperator(ExprBinOp expr) { PREDEFMETH pdm; switch (expr.Kind) { case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT; break; case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT; break; case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR; break; case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR; break; case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND; break; case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO; break; case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE; break; case ExpressionKind.StringEq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.Eq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.StringNotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.NotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.GreaterThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL; break; case ExpressionKind.LessThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL; break; case ExpressionKind.LessThan: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN; break; case ExpressionKind.GreaterThan: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN; break; case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO; break; case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE; break; case ExpressionKind.Multiply: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED : PREDEFMETH.PM_EXPRESSION_MULTIPLY); break; case ExpressionKind.Subtract: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED : PREDEFMETH.PM_EXPRESSION_SUBTRACT); break; case ExpressionKind.Add: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED : PREDEFMETH.PM_EXPRESSION_ADD); break; default: throw Error.InternalCompilerError(); } Expr optionalLeftChild = expr.OptionalLeftChild; Expr optionalRightChild = expr.OptionalRightChild; CType cType = optionalLeftChild.Type; CType cType2 = optionalRightChild.Type; Expr arg = Visit(optionalLeftChild); Expr expr2 = Visit(optionalRightChild); bool flag = false; CType cType3 = null; CType cType4 = null; NullableType nullableType; if (cType.IsEnumType) { cType3 = TypeManager.GetNullable(cType.UnderlyingEnumType); cType = cType3; flag = true; } else if ((nullableType = (cType as NullableType)) != null && nullableType.UnderlyingType.IsEnumType) { cType3 = TypeManager.GetNullable(nullableType.UnderlyingType.UnderlyingEnumType); cType = cType3; flag = true; } NullableType nullableType2; if (cType2.IsEnumType) { cType4 = TypeManager.GetNullable(cType2.UnderlyingEnumType); cType2 = cType4; flag = true; } else if ((nullableType2 = (cType2 as NullableType)) != null && nullableType2.UnderlyingType.IsEnumType) { cType4 = TypeManager.GetNullable(nullableType2.UnderlyingType.UnderlyingEnumType); cType2 = cType4; flag = true; } NullableType nullableType3; if ((nullableType3 = (cType as NullableType)) != null && nullableType3.UnderlyingType == cType2) cType4 = cType; NullableType nullableType4; if ((nullableType4 = (cType2 as NullableType)) != null && nullableType4.UnderlyingType == cType) cType3 = cType2; if (cType3 != null) arg = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, arg, CreateTypeOf(cType3)); if (cType4 != null) expr2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr2, CreateTypeOf(cType4)); Expr expr3 = GenerateCall(pdm, arg, expr2); if (flag && expr.Type.StripNubs().IsEnumType) expr3 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr3, CreateTypeOf(expr.Type)); return expr3; } private Expr GenerateBuiltInUnaryOperator(ExprUnaryOp expr) { PREDEFMETH pdm; switch (expr.Kind) { case ExpressionKind.UnaryPlus: return Visit(expr.Child); case ExpressionKind.BitwiseNot: pdm = PREDEFMETH.PM_EXPRESSION_NOT; break; case ExpressionKind.LogicalNot: pdm = PREDEFMETH.PM_EXPRESSION_NOT; break; case ExpressionKind.Negate: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED : PREDEFMETH.PM_EXPRESSION_NEGATE); break; default: throw Error.InternalCompilerError(); } Expr child = expr.Child; return GenerateCall(pdm, Visit(child)); } private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr) { 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.Eq: case ExpressionKind.NotEq: case ExpressionKind.LessThan: case ExpressionKind.LessThanOrEqual: case ExpressionKind.GreaterThan: case ExpressionKind.GreaterThanOrEqual: case ExpressionKind.StringEq: case ExpressionKind.StringNotEq: case ExpressionKind.DelegateEq: case ExpressionKind.DelegateNotEq: return GenerateUserDefinedComparisonOperator(expr); case ExpressionKind.Subtract: case ExpressionKind.DelegateSubtract: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED); break; case ExpressionKind.Add: case ExpressionKind.DelegateAdd: 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 pp = expr.OptionalLeftChild; Expr pp2 = expr.OptionalRightChild; Expr optionalUserDefinedCall = expr.OptionalUserDefinedCall; if (optionalUserDefinedCall != null) { ExprCall exprCall; if ((exprCall = (optionalUserDefinedCall as ExprCall)) != null) { ExprList exprList = (ExprList)exprCall.OptionalArguments; pp = exprList.OptionalElement; pp2 = exprList.OptionalNextListNode; } else { ExprUserLogicalOp exprUserLogicalOp = optionalUserDefinedCall as ExprUserLogicalOp; ExprList exprList2 = (ExprList)exprUserLogicalOp.OperatorCall.OptionalArguments; pp = ((ExprWrap)exprList2.OptionalElement).OptionalExpression; pp2 = exprList2.OptionalNextListNode; } } pp = Visit(pp); pp2 = Visit(pp2); FixLiftedUserDefinedBinaryOperators(expr, ref pp, ref pp2); Expr arg = ExprFactory.CreateMethodInfo(expr.UserDefinedCallMethod); Expr expr2 = GenerateCall(pdm, pp, pp2, arg); if (expr.Kind == ExpressionKind.DelegateSubtract || expr.Kind == ExpressionKind.DelegateAdd) { Expr arg2 = CreateTypeOf(expr.Type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr2, arg2); } return expr2; } private Expr GenerateUserDefinedUnaryOperator(ExprUnaryOp expr) { Expr pExpr = expr.Child; ExprCall exprCall = (ExprCall)expr.OptionalUserDefinedCall; if (exprCall != null) pExpr = exprCall.OptionalArguments; ExpressionKind kind = expr.Kind; if (kind > ExpressionKind.UnaryPlus) { switch (kind) { case ExpressionKind.BitwiseNot: goto IL_007a; case ExpressionKind.DecimalNegate: goto IL_0084; } if ((uint)(kind - 69) <= 1) goto IL_0095; goto IL_009a; } switch (kind) { case ExpressionKind.True: case ExpressionKind.False: return Visit(exprCall); case ExpressionKind.UnaryPlus: break; case ExpressionKind.LogicalNot: goto IL_007f; case ExpressionKind.Negate: goto IL_0084; case ExpressionKind.Inc: case ExpressionKind.Dec: goto IL_0095; default: goto IL_009a; } PREDEFMETH pdm = PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED; goto IL_00a0; IL_007a: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; goto IL_00a0; IL_0095: pdm = PREDEFMETH.PM_EXPRESSION_CALL; goto IL_00a0; IL_009a: throw Error.InternalCompilerError(); IL_0084: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED); goto IL_00a0; IL_007f: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; goto IL_00a0; IL_00a0: Expr expr2 = Visit(pExpr); Expr arg = 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, arg, GenerateParamsArray(expr2, PredefinedType.PT_EXPRESSION)); return GenerateCall(pdm, expr2, arg); } private Expr GenerateUserDefinedComparisonOperator(ExprBinOp expr) { 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 pp = expr.OptionalLeftChild; Expr pp2 = expr.OptionalRightChild; if (expr.OptionalUserDefinedCall != null) { ExprCall exprCall = (ExprCall)expr.OptionalUserDefinedCall; ExprList exprList = (ExprList)exprCall.OptionalArguments; pp = exprList.OptionalElement; pp2 = exprList.OptionalNextListNode; } pp = Visit(pp); pp2 = Visit(pp2); FixLiftedUserDefinedBinaryOperators(expr, ref pp, ref pp2); Expr arg = ExprFactory.CreateBoolConstant(false); Expr arg2 = ExprFactory.CreateMethodInfo(expr.UserDefinedCallMethod); return GenerateCall(pdm, pp, pp2, arg, arg2); } private Expr GenerateConversion(Expr arg, CType CType, bool bChecked) { return GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked()); } private static Expr GenerateConversionWithSource(Expr pTarget, CType pType, bool bChecked) { PREDEFMETH pdm = bChecked ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; Expr arg = CreateTypeOf(pType); return GenerateCall(pdm, pTarget, arg); } private Expr GenerateValueAccessConversion(Expr pArgument) { CType type = pArgument.Type.StripNubs(); Expr arg = CreateTypeOf(type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, Visit(pArgument), arg); } private Expr GenerateUserDefinedConversion(Expr arg, CType type, MethWithInst method) { Expr target = Visit(arg); return GenerateUserDefinedConversion(arg, type, target, method); } private static Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr target, MethWithInst method) { if (isEnumToDecimalConversion(arg.Type, CType)) { CType underlyingEnumType = arg.Type.StripNubs().UnderlyingEnumType; CType nullable = TypeManager.GetNullable(underlyingEnumType); Expr arg2 = CreateTypeOf(nullable); target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, arg2); } CType cType = TypeManager.SubstType(method.Meth().RetType, method.GetType(), method.TypeArgs); bool flag = cType == CType || (IsNullableValueType(arg.Type) && IsNullableValueType(CType)); Expr arg3 = CreateTypeOf(flag ? CType : cType); Expr arg4 = ExprFactory.CreateMethodInfo(method); PREDEFMETH pdm = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED; Expr expr = GenerateCall(pdm, target, arg3, arg4); if (flag) return expr; PREDEFMETH pdm2 = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; Expr arg5 = CreateTypeOf(CType); return GenerateCall(pdm2, expr, arg5); } private Expr GenerateUserDefinedConversion(ExprUserDefinedConversion pExpr, Expr pArgument) { Expr userDefinedCall = pExpr.UserDefinedCall; Expr argument = pExpr.Argument; Expr target; if (!isEnumToDecimalConversion(pArgument.Type, pExpr.Type) && IsNullableValueAccess(argument, pArgument)) target = GenerateValueAccessConversion(pArgument); else { ExprCall exprCall = userDefinedCall as ExprCall; Expr expr = exprCall?.PConversions; if (expr != null) { ExprCall exprCall2; if ((exprCall2 = (expr as ExprCall)) != null) { Expr optionalArguments = exprCall2.OptionalArguments; target = ((!IsNullableValueAccess(optionalArguments, pArgument)) ? Visit(optionalArguments) : GenerateValueAccessConversion(pArgument)); return GenerateConversionWithSource(target, userDefinedCall.Type, exprCall.isChecked()); } return GenerateUserDefinedConversion((ExprUserDefinedConversion)expr, pArgument); } target = Visit(argument); } return GenerateUserDefinedConversion(argument, pExpr.Type, target, pExpr.UserDefinedCallMethod); } private static Expr GenerateParameter(string name, CType CType) { SymbolLoader.GetPredefindType(PredefinedType.PT_STRING); ExprConstant arg = ExprFactory.CreateStringConstant(name); ExprTypeOf arg2 = CreateTypeOf(CType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_PARAMETER, arg2, arg); } private static MethodSymbol GetPreDefMethod(PREDEFMETH pdm) { return PredefinedMembers.GetMethod(pdm); } private static ExprTypeOf CreateTypeOf(CType type) { return ExprFactory.CreateTypeOf(type); } private static Expr CreateWraps(ExprBoundLambda anonmeth) { Expr expr = null; for (Symbol symbol = anonmeth.ArgumentScope.firstChild; symbol != null; symbol = symbol.nextChild) { LocalVariableSymbol localVariableSymbol; if ((localVariableSymbol = (symbol as LocalVariableSymbol)) != null) { Expr expression = GenerateParameter(localVariableSymbol.name.Text, localVariableSymbol.GetType()); localVariableSymbol.wrap = ExprFactory.CreateWrap(expression); Expr expr2 = ExprFactory.CreateSave(localVariableSymbol.wrap); expr = ((expr != null) ? ExprFactory.CreateSequence(expr, expr2) : expr2); } } return expr; } private Expr GenerateConstructor(ExprCall expr) { Expr arg = ExprFactory.CreateMethodInfo(expr.MethWithInst); Expr args = GenerateArgsList(expr.OptionalArguments); Expr arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW, arg, arg2); } private Expr GenerateArgsList(Expr oldArgs) { Expr first = null; Expr last = first; ExpressionIterator expressionIterator = new ExpressionIterator(oldArgs); while (!expressionIterator.AtEnd()) { Expr pExpr = expressionIterator.Current(); ExprFactory.AppendItemToList(Visit(pExpr), ref first, ref last); expressionIterator.MoveNext(); } return first; } private Expr GenerateIndexList(Expr oldIndices) { CType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_INT); Expr first = null; Expr last = first; ExpressionIterator expressionIterator = new ExpressionIterator(oldIndices); while (!expressionIterator.AtEnd()) { Expr expr = expressionIterator.Current(); if (expr.Type != predefindType) { expr = ExprFactory.CreateCast(EXPRFLAG.EXF_LITERALCONST, predefindType, expr); expr.Flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } Expr newItem = Visit(expr); ExprFactory.AppendItemToList(newItem, ref first, ref last); expressionIterator.MoveNext(); } return first; } private static Expr GenerateConstant(Expr expr) { EXPRFLAG flags = (EXPRFLAG)0; AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT); if (expr.Type is NullType) { ExprTypeOf arg = CreateTypeOf(predefindType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, expr, arg); } AggregateType predefindType2 = SymbolLoader.GetPredefindType(PredefinedType.PT_STRING); if (expr.Type != predefindType2) flags = EXPRFLAG.EXF_CTOR; ExprCast arg2 = ExprFactory.CreateCast(flags, predefindType, expr); ExprTypeOf arg3 = CreateTypeOf(expr.Type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, arg2, arg3); } private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); MethWithInst methWithInst = new MethWithInst(preDefMethod, predefindType); ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arg1, memberGroup, methWithInst); exprCall.PredefinedMethod = pdm; return exprCall; } private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); Expr arguments = ExprFactory.CreateList(arg1, arg2); MethWithInst methWithInst = new MethWithInst(preDefMethod, predefindType); ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arguments, memberGroup, methWithInst); exprCall.PredefinedMethod = pdm; return exprCall; } private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); Expr arguments = ExprFactory.CreateList(arg1, arg2, arg3); MethWithInst methWithInst = new MethWithInst(preDefMethod, predefindType); ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arguments, memberGroup, methWithInst); exprCall.PredefinedMethod = pdm; return exprCall; } private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3, Expr arg4) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); Expr arguments = ExprFactory.CreateList(arg1, arg2, arg3, arg4); MethWithInst methWithInst = new MethWithInst(preDefMethod, predefindType); ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arguments, memberGroup, methWithInst); exprCall.PredefinedMethod = pdm; return exprCall; } private static ExprArrayInit GenerateParamsArray(Expr args, PredefinedType pt) { int num = ExpressionIterator.Count(args); AggregateType predefindType = SymbolLoader.GetPredefindType(pt); ArrayType array = TypeManager.GetArray(predefindType, 1, true); ExprConstant argumentDimensions = ExprFactory.CreateIntegerConstant(num); return ExprFactory.CreateArrayInit(array, args, argumentDimensions, new int[1] { num }); } private static void FixLiftedUserDefinedBinaryOperators(ExprBinOp expr, ref Expr pp1, ref Expr pp2) { MethodSymbol methodSymbol = expr.UserDefinedCallMethod.Meth(); Expr optionalLeftChild = expr.OptionalLeftChild; Expr optionalRightChild = expr.OptionalRightChild; Expr expr2 = pp1; Expr expr3 = pp2; CType cType = methodSymbol.Params[0]; CType cType2 = methodSymbol.Params[1]; CType type = optionalLeftChild.Type; CType type2 = optionalRightChild.Type; AggregateType aggregateType2; AggregateType aggregateType; if ((aggregateType = (cType as AggregateType)) != null && aggregateType.OwningAggregate.IsValueType() && (aggregateType2 = (cType2 as AggregateType)) != null && aggregateType2.OwningAggregate.IsValueType()) { CType nullable = TypeManager.GetNullable(cType); CType nullable2 = TypeManager.GetNullable(cType2); if (type is NullType || (type == cType && (type2 == nullable2 || type2 is NullType))) expr2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr2, CreateTypeOf(nullable)); if (type2 is NullType || (type2 == cType2 && (type == nullable || type is NullType))) expr3 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr3, CreateTypeOf(nullable2)); pp1 = expr2; pp2 = expr3; } } private static bool IsNullableValueType(CType pType) { AggregateType aggregateType; if (pType is NullableType && (aggregateType = (pType.StripNubs() as AggregateType)) != null) return aggregateType.OwningAggregate.IsValueType(); return false; } private static bool IsNullableValueAccess(Expr pExpr, Expr pObject) { ExprProperty exprProperty; if ((exprProperty = (pExpr as ExprProperty)) != null && exprProperty.MemberGroup.OptionalObject == pObject) return pObject.Type is NullableType; return false; } private static bool isEnumToDecimalConversion(CType argtype, CType desttype) { if (argtype.StripNubs().IsEnumType) return desttype.StripNubs().IsPredefType(PredefinedType.PT_DECIMAL); return false; } } }