<PackageReference Include="Microsoft.CSharp" Version="4.6.0-preview3.19128.7" />

ExpressionTreeRewriter

using Microsoft.CSharp.RuntimeBinder.Syntax; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal class ExpressionTreeRewriter : ExprVisitorBase { protected ExprFactory expressionFactory; protected SymbolLoader symbolLoader; protected EXPRBOUNDLAMBDA currentAnonMeth; protected bool alwaysRewrite; public static EXPR Rewrite(EXPR expr, ExprFactory expressionFactory, SymbolLoader symbolLoader) { ExpressionTreeRewriter expressionTreeRewriter = new ExpressionTreeRewriter(expressionFactory, symbolLoader); expressionTreeRewriter.alwaysRewrite = true; return expressionTreeRewriter.Visit(expr); } protected ExprFactory GetExprFactory() { return expressionFactory; } protected SymbolLoader GetSymbolLoader() { return symbolLoader; } protected ExpressionTreeRewriter(ExprFactory expressionFactory, SymbolLoader symbolLoader) { this.expressionFactory = expressionFactory; this.symbolLoader = symbolLoader; alwaysRewrite = false; } protected override EXPR Dispatch(EXPR expr) { EXPR eXPR = base.Dispatch(expr); if (eXPR == expr) throw Error.InternalCompilerError(); return eXPR; } protected override EXPR VisitASSIGNMENT(EXPRASSIGNMENT assignment) { EXPR arg; if (assignment.GetLHS().isPROP()) { EXPRPROP eXPRPROP = assignment.GetLHS().asPROP(); if (eXPRPROP.GetOptionalArguments() == null) arg = Visit(eXPRPROP); else { EXPR arg2 = Visit(eXPRPROP.GetMemberGroup().GetOptionalObject()); EXPR arg3 = GetExprFactory().CreatePropertyInfo(eXPRPROP.pwtSlot.Prop(), eXPRPROP.pwtSlot.Ats); EXPR arg4 = GenerateParamsArray(GenerateArgsList(eXPRPROP.GetOptionalArguments()), PredefinedType.PT_EXPRESSION); arg = GenerateCall(PREDEFMETH.PM_EXPRESSION_PROPERTY, arg2, arg3, arg4); } } else arg = Visit(assignment.GetLHS()); EXPR arg5 = Visit(assignment.GetRHS()); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ASSIGN, arg, arg5); } protected override EXPR VisitMULTIGET(EXPRMULTIGET pExpr) { return Visit(pExpr.GetOptionalMulti().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); } protected override EXPR VisitBOUNDLAMBDA(EXPRBOUNDLAMBDA anonmeth) { EXPRBOUNDLAMBDA eXPRBOUNDLAMBDA = currentAnonMeth; currentAnonMeth = anonmeth; MethodSymbol preDefMethod = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA); CType cType = anonmeth.DelegateType(); TypeArray typeArgs = GetSymbolLoader().getBSymmgr().AllocParams(1, new CType[1] { cType }); AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); MethWithInst methWithInst = new MethWithInst(preDefMethod, optPredefTypeErr, typeArgs); EXPR eXPR = CreateWraps(anonmeth); EXPR op = RewriteLambdaBody(anonmeth); EXPR op2 = RewriteLambdaParameters(anonmeth); EXPR pOptionalArguments = GetExprFactory().CreateList(op, op2); CType pType = GetSymbolLoader().GetTypeManager().SubstType(methWithInst.Meth().RetType, methWithInst.GetType(), methWithInst.TypeArgs); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst); EXPR eXPR2 = GetExprFactory().CreateCall((EXPRFLAG)0, pType, pOptionalArguments, pMemberGroup, methWithInst); eXPR2.asCALL().PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA; currentAnonMeth = eXPRBOUNDLAMBDA; if (eXPR != null) eXPR2 = GetExprFactory().CreateSequence(eXPR, eXPR2); EXPR eXPR3 = DestroyWraps(anonmeth, eXPR2); if (currentAnonMeth != null) eXPR3 = GenerateCall(PREDEFMETH.PM_EXPRESSION_QUOTE, eXPR3); return eXPR3; } protected override EXPR VisitCONSTANT(EXPRCONSTANT expr) { return GenerateConstant(expr); } protected override EXPR VisitLOCAL(EXPRLOCAL local) { if (local.local.wrap != null) return local.local.wrap; return GetExprFactory().CreateHoistedLocalInExpression(local); } protected override EXPR VisitTHISPOINTER(EXPRTHISPOINTER expr) { return GenerateConstant(expr); } protected override EXPR VisitFIELD(EXPRFIELD expr) { EXPR arg = (expr.GetOptionalObject() != null) ? Visit(expr.GetOptionalObject()) : GetExprFactory().CreateNull(); EXPRFIELDINFO arg2 = GetExprFactory().CreateFieldInfo(expr.fwt.Field(), expr.fwt.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.GetArgument(); if (argument.type == pExpr.type || GetSymbolLoader().IsBaseClassOfClass(argument.type, pExpr.type) || CConversions.FImpRefConv(GetSymbolLoader(), argument.type, pExpr.type)) return Visit(argument); if (pExpr.type != null && pExpr.type.isPredefType(PredefinedType.PT_G_EXPRESSION) && argument.isBOUNDLAMBDA()) 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.GetFirstArgument().type.isPredefType(PredefinedType.PT_STRING) || !expr.GetSecondArgument().type.isPredefType(PredefinedType.PT_STRING)) ? PREDEFMETH.PM_STRING_CONCAT_OBJECT_2 : PREDEFMETH.PM_STRING_CONCAT_STRING_2; EXPR arg = Visit(expr.GetFirstArgument()); EXPR arg2 = Visit(expr.GetSecondArgument()); MethodSymbol preDefMethod = GetPreDefMethod(pdm); EXPR arg3 = GetExprFactory().CreateMethodInfo(preDefMethod, GetSymbolLoader().GetReqPredefType(PredefinedType.PT_STRING), null); return GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, arg, arg2, arg3); } protected override EXPR VisitBINOP(EXPRBINOP expr) { if ((SymWithType)expr.GetUserDefinedCallMethod() != (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.GetArray()); EXPR eXPR = GenerateIndexList(pExpr.GetIndex()); if (eXPR.isLIST()) { 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 VisitARRAYLENGTH(EXPRARRAYLENGTH pExpr) { return GenerateBuiltInUnaryOperator(PREDEFMETH.PM_EXPRESSION_ARRAYLENGTH, pExpr.GetArray(), pExpr); } protected override EXPR VisitQUESTIONMARK(EXPRQUESTIONMARK pExpr) { EXPR arg = Visit(pExpr.GetTestExpression()); EXPR arg2 = GenerateQuestionMarkOperand(pExpr.GetConsequence().asBINOP().GetOptionalLeftChild()); EXPR arg3 = GenerateQuestionMarkOperand(pExpr.GetConsequence().asBINOP().GetOptionalRightChild()); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONDITION, arg, arg2, arg3); } protected override EXPR VisitCALL(EXPRCALL expr) { switch (expr.nubLiftKind) { case NullableCallLiftKind.NullableConversion: case NullableCallLiftKind.NullableConversionConstructor: case NullableCallLiftKind.NullableIntermediateConversion: return GenerateConversion(expr.GetOptionalArguments(), expr.type, expr.isChecked()); case NullableCallLiftKind.UserDefinedConversion: case NullableCallLiftKind.NotLiftedIntermediateConversion: return GenerateUserDefinedConversion(expr.GetOptionalArguments(), expr.type, expr.mwi); default: { if (expr.mwi.Meth().IsConstructor()) return GenerateConstructor(expr); EXPRMEMGRP memberGroup = expr.GetMemberGroup(); if (memberGroup.isDelegate()) return GenerateDelegateInvoke(expr); EXPR arg; if (expr.mwi.Meth().isStatic || expr.GetMemberGroup().GetOptionalObject() == null) arg = GetExprFactory().CreateNull(); else { arg = expr.GetMemberGroup().GetOptionalObject(); if (arg != null && arg.isCAST() && arg.asCAST().IsBoxingCast()) arg = arg.asCAST().GetArgument(); arg = Visit(arg); } EXPR arg2 = GetExprFactory().CreateMethodInfo(expr.mwi); EXPR args = GenerateArgsList(expr.GetOptionalArguments()); EXPR arg3 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); PREDEFMETH pdm = PREDEFMETH.PM_EXPRESSION_CALL; return GenerateCall(pdm, arg, arg2, arg3); } } } protected override EXPR VisitPROP(EXPRPROP expr) { EXPR arg = (!expr.pwtSlot.Prop().isStatic && expr.GetMemberGroup().GetOptionalObject() != null) ? Visit(expr.GetMemberGroup().GetOptionalObject()) : GetExprFactory().CreateNull(); EXPR arg2 = GetExprFactory().CreatePropertyInfo(expr.pwtSlot.Prop(), expr.pwtSlot.GetType()); if (expr.GetOptionalArguments() != null) { EXPR args = GenerateArgsList(expr.GetOptionalArguments()); 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(EXPRARRINIT expr) { EXPR arg = CreateTypeOf(expr.type.AsArrayType().GetElementType()); EXPR args = GenerateArgsList(expr.GetOptionalArguments()); EXPR arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT, arg, arg2); } protected override EXPR VisitZEROINIT(EXPRZEROINIT expr) { if (expr.IsConstructor) { EXPRTYPEOF arg = CreateTypeOf(expr.type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW_TYPE, arg); } return GenerateConstant(expr); } protected override EXPR VisitTYPEOF(EXPRTYPEOF expr) { return GenerateConstant(expr); } protected virtual EXPR GenerateQuestionMarkOperand(EXPR pExpr) { if (pExpr.isCAST()) return GenerateConversion(pExpr.asCAST().GetArgument(), pExpr.type, pExpr.isChecked()); return Visit(pExpr); } protected virtual EXPR GenerateDelegateInvoke(EXPRCALL expr) { EXPRMEMGRP memberGroup = expr.GetMemberGroup(); EXPR optionalObject = memberGroup.GetOptionalObject(); EXPR arg = Visit(optionalObject); EXPR args = GenerateArgsList(expr.GetOptionalArguments()); EXPR arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); return GenerateCall(PREDEFMETH.PM_EXPRESSION_INVOKE, arg, arg2); } protected virtual EXPR GenerateBuiltInBinaryOperator(EXPRBINOP expr) { PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_LSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT; break; case ExpressionKind.EK_RSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT; break; case ExpressionKind.EK_BITXOR: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR; break; case ExpressionKind.EK_BITOR: pdm = PREDEFMETH.PM_EXPRESSION_OR; break; case ExpressionKind.EK_BITAND: pdm = PREDEFMETH.PM_EXPRESSION_AND; break; case ExpressionKind.EK_LOGAND: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO; break; case ExpressionKind.EK_LOGOR: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE; break; case ExpressionKind.EK_STRINGEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.EK_EQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.EK_STRINGNE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.EK_NE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.EK_GE: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL; break; case ExpressionKind.EK_LE: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL; break; case ExpressionKind.EK_LT: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN; break; case ExpressionKind.EK_GT: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN; break; case ExpressionKind.EK_MOD: pdm = PREDEFMETH.PM_EXPRESSION_MODULO; break; case ExpressionKind.EK_DIV: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE; break; case ExpressionKind.EK_MUL: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED : PREDEFMETH.PM_EXPRESSION_MULTIPLY); break; case ExpressionKind.EK_SUB: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED : PREDEFMETH.PM_EXPRESSION_SUBTRACT); break; case ExpressionKind.EK_ADD: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED : PREDEFMETH.PM_EXPRESSION_ADD); break; default: throw Error.InternalCompilerError(); } EXPR optionalLeftChild = expr.GetOptionalLeftChild(); EXPR optionalRightChild = expr.GetOptionalRightChild(); CType cType = optionalLeftChild.type; CType cType2 = optionalRightChild.type; EXPR arg = Visit(optionalLeftChild); EXPR eXPR = Visit(optionalRightChild); bool flag = false; CType cType3 = null; CType cType4 = null; if (cType.isEnumType()) { cType3 = GetSymbolLoader().GetTypeManager().GetNullable(cType.underlyingEnumType()); cType = cType3; flag = true; } else if (cType.IsNullableType() && cType.StripNubs().isEnumType()) { cType3 = GetSymbolLoader().GetTypeManager().GetNullable(cType.StripNubs().underlyingEnumType()); cType = cType3; flag = true; } if (cType2.isEnumType()) { cType4 = GetSymbolLoader().GetTypeManager().GetNullable(cType2.underlyingEnumType()); cType2 = cType4; flag = true; } else if (cType2.IsNullableType() && cType2.StripNubs().isEnumType()) { cType4 = GetSymbolLoader().GetTypeManager().GetNullable(cType2.StripNubs().underlyingEnumType()); cType2 = cType4; flag = true; } if (cType.IsNullableType() && cType.StripNubs() == cType2) cType4 = cType; if (cType2.IsNullableType() && cType2.StripNubs() == cType) cType3 = cType2; if (cType3 != null) arg = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, arg, CreateTypeOf(cType3)); if (cType4 != null) eXPR = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR, CreateTypeOf(cType4)); EXPR eXPR2 = GenerateCall(pdm, arg, eXPR); if (flag && expr.type.StripNubs().isEnumType()) eXPR2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR2, CreateTypeOf(expr.type)); return eXPR2; } protected virtual EXPR GenerateBuiltInUnaryOperator(EXPRUNARYOP expr) { PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_UPLUS: return Visit(expr.Child); case ExpressionKind.EK_BITNOT: pdm = PREDEFMETH.PM_EXPRESSION_NOT; break; case ExpressionKind.EK_LOGNOT: pdm = PREDEFMETH.PM_EXPRESSION_NOT; break; case ExpressionKind.EK_NEG: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED : PREDEFMETH.PM_EXPRESSION_NEGATE); break; default: throw Error.InternalCompilerError(); } EXPR child = expr.Child; return GenerateBuiltInUnaryOperator(pdm, child, expr); } protected virtual EXPR GenerateBuiltInUnaryOperator(PREDEFMETH pdm, EXPR pOriginalOperator, EXPR pOperator) { EXPR arg = Visit(pOriginalOperator); if (pOriginalOperator.type.IsNullableType() && pOriginalOperator.type.StripNubs().isEnumType()) { CType pUnderlyingType = pOriginalOperator.type.StripNubs().underlyingEnumType(); CType nullable = GetSymbolLoader().GetTypeManager().GetNullable(pUnderlyingType); arg = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, arg, CreateTypeOf(nullable)); } EXPR eXPR = GenerateCall(pdm, arg); if (pOriginalOperator.type.IsNullableType() && pOriginalOperator.type.StripNubs().isEnumType()) eXPR = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR, CreateTypeOf(pOperator.type)); return eXPR; } protected virtual EXPR GenerateUserDefinedBinaryOperator(EXPRBINOP expr) { PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_LOGOR: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED; break; case ExpressionKind.EK_LOGAND: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED; break; case ExpressionKind.EK_LSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED; break; case ExpressionKind.EK_RSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED; break; case ExpressionKind.EK_BITXOR: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED; break; case ExpressionKind.EK_BITOR: pdm = PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED; break; case ExpressionKind.EK_BITAND: pdm = PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED; break; case ExpressionKind.EK_MOD: pdm = PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED; break; case ExpressionKind.EK_DIV: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED; break; case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: case ExpressionKind.EK_STRINGEQ: case ExpressionKind.EK_STRINGNE: case ExpressionKind.EK_DELEGATEEQ: case ExpressionKind.EK_DELEGATENE: return GenerateUserDefinedComparisonOperator(expr); case ExpressionKind.EK_SUB: case ExpressionKind.EK_DELEGATESUB: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED); break; case ExpressionKind.EK_ADD: case ExpressionKind.EK_DELEGATEADD: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED); break; case ExpressionKind.EK_MUL: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED); break; default: throw Error.InternalCompilerError(); } EXPR pp = expr.GetOptionalLeftChild(); EXPR pp2 = expr.GetOptionalRightChild(); EXPR optionalUserDefinedCall = expr.GetOptionalUserDefinedCall(); if (optionalUserDefinedCall != null) { if (optionalUserDefinedCall.kind == ExpressionKind.EK_CALL) { EXPRLIST eXPRLIST = optionalUserDefinedCall.asCALL().GetOptionalArguments().asLIST(); pp = eXPRLIST.GetOptionalElement(); pp2 = eXPRLIST.GetOptionalNextListNode(); } else { EXPRLIST eXPRLIST2 = optionalUserDefinedCall.asUSERLOGOP().OperatorCall.GetOptionalArguments().asLIST(); pp = eXPRLIST2.GetOptionalElement().asWRAP().GetOptionalExpression(); pp2 = eXPRLIST2.GetOptionalNextListNode(); } } pp = Visit(pp); pp2 = Visit(pp2); FixLiftedUserDefinedBinaryOperators(expr, ref pp, ref pp2); EXPR arg = GetExprFactory().CreateMethodInfo(expr.GetUserDefinedCallMethod()); EXPR eXPR = GenerateCall(pdm, pp, pp2, arg); if (expr.kind == ExpressionKind.EK_DELEGATESUB || expr.kind == ExpressionKind.EK_DELEGATEADD) { EXPR arg2 = CreateTypeOf(expr.type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR, arg2); } return eXPR; } protected virtual EXPR GenerateUserDefinedUnaryOperator(EXPRUNARYOP expr) { EXPR pExpr = expr.Child; EXPRCALL eXPRCALL = expr.OptionalUserDefinedCall.asCALL(); if (eXPRCALL != null) pExpr = eXPRCALL.GetOptionalArguments(); PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_TRUE: case ExpressionKind.EK_FALSE: return Visit(eXPRCALL); case ExpressionKind.EK_UPLUS: pdm = PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED; break; case ExpressionKind.EK_BITNOT: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; break; case ExpressionKind.EK_LOGNOT: pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED; break; case ExpressionKind.EK_NEG: case ExpressionKind.EK_DECIMALNEG: pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED); break; case ExpressionKind.EK_INC: case ExpressionKind.EK_DEC: case ExpressionKind.EK_DECIMALINC: case ExpressionKind.EK_DECIMALDEC: pdm = PREDEFMETH.PM_EXPRESSION_CALL; break; default: throw Error.InternalCompilerError(); } EXPR eXPR = Visit(pExpr); EXPR arg = GetExprFactory().CreateMethodInfo(expr.UserDefinedCallMethod); if (expr.kind == ExpressionKind.EK_INC || expr.kind == ExpressionKind.EK_DEC || expr.kind == ExpressionKind.EK_DECIMALINC || expr.kind == ExpressionKind.EK_DECIMALDEC) return GenerateCall(pdm, null, arg, GenerateParamsArray(eXPR, PredefinedType.PT_EXPRESSION)); return GenerateCall(pdm, eXPR, arg); } protected virtual EXPR GenerateUserDefinedComparisonOperator(EXPRBINOP expr) { PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_STRINGEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_STRINGNE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_DELEGATEEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_DELEGATENE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_EQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_NE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_LE: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED; break; case ExpressionKind.EK_LT: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED; break; case ExpressionKind.EK_GE: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED; break; case ExpressionKind.EK_GT: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED; break; default: throw Error.InternalCompilerError(); } EXPR pp = expr.GetOptionalLeftChild(); EXPR pp2 = expr.GetOptionalRightChild(); if (expr.GetOptionalUserDefinedCall() != null) { EXPRCALL eXPRCALL = expr.GetOptionalUserDefinedCall().asCALL(); EXPRLIST eXPRLIST = eXPRCALL.GetOptionalArguments().asLIST(); pp = eXPRLIST.GetOptionalElement(); pp2 = eXPRLIST.GetOptionalNextListNode(); } pp = Visit(pp); pp2 = Visit(pp2); FixLiftedUserDefinedBinaryOperators(expr, ref pp, ref pp2); EXPR arg = GetExprFactory().CreateBoolConstant(false); EXPR arg2 = GetExprFactory().CreateMethodInfo(expr.GetUserDefinedCallMethod()); return GenerateCall(pdm, pp, pp2, arg, arg2); } protected EXPR RewriteLambdaBody(EXPRBOUNDLAMBDA anonmeth) { EXPRBLOCK optionalBody = anonmeth.OptionalBody; if (optionalBody.GetOptionalStatements().isRETURN()) return Visit(optionalBody.GetOptionalStatements().asRETURN().GetOptionalObject()); throw Error.InternalCompilerError(); } protected EXPR RewriteLambdaParameters(EXPRBOUNDLAMBDA anonmeth) { EXPR first = null; EXPR last = first; for (Symbol symbol = anonmeth.ArgumentScope(); symbol != null; symbol = symbol.nextChild) { if (symbol.IsLocalVariableSymbol()) { LocalVariableSymbol localVariableSymbol = symbol.AsLocalVariableSymbol(); if (!localVariableSymbol.isThis) GetExprFactory().AppendItemToList(localVariableSymbol.wrap, ref first, ref last); } } return GenerateParamsArray(first, PredefinedType.PT_PARAMETEREXPRESSION); } protected virtual EXPR GenerateConversion(EXPR arg, CType CType, bool bChecked) { return GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked()); } protected virtual 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); } protected virtual EXPR GenerateValueAccessConversion(EXPR pArgument) { CType cType = pArgument.type.StripNubs(); EXPR arg = CreateTypeOf(cType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, Visit(pArgument), arg); } protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType type, MethWithInst method) { EXPR target = Visit(arg); return GenerateUserDefinedConversion(arg, type, target, method); } protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType CType, EXPR target, MethWithInst method) { if (isEnumToDecimalConversion(arg.type, CType)) { CType pUnderlyingType = arg.type.StripNubs().underlyingEnumType(); CType nullable = GetSymbolLoader().GetTypeManager().GetNullable(pUnderlyingType); EXPR arg2 = CreateTypeOf(nullable); target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, arg2); } CType cType = GetSymbolLoader().GetTypeManager().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 = GetExprFactory().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); } protected virtual EXPR GenerateUserDefinedConversion(EXPRUSERDEFINEDCONVERSION pExpr, EXPR pArgument) { EXPR userDefinedCall = pExpr.UserDefinedCall; EXPR argument = pExpr.Argument; EXPR eXPR = null; if (!isEnumToDecimalConversion(pArgument.type, pExpr.type) && IsNullableValueAccess(argument, pArgument)) eXPR = GenerateValueAccessConversion(pArgument); else { if (userDefinedCall.isCALL() && userDefinedCall.asCALL().pConversions != null) { EXPR pConversions = userDefinedCall.asCALL().pConversions; if (pConversions.isCALL()) { EXPR optionalArguments = pConversions.asCALL().GetOptionalArguments(); eXPR = ((!IsNullableValueAccess(optionalArguments, pArgument)) ? Visit(optionalArguments) : GenerateValueAccessConversion(pArgument)); return GenerateConversionWithSource(eXPR, userDefinedCall.type, userDefinedCall.asCALL().isChecked()); } return GenerateUserDefinedConversion(pConversions.asUSERDEFINEDCONVERSION(), pArgument); } eXPR = Visit(argument); } return GenerateUserDefinedConversion(argument, pExpr.type, eXPR, pExpr.UserDefinedCallMethod); } protected virtual EXPR GenerateParameter(string name, CType CType) { GetSymbolLoader().GetReqPredefType(PredefinedType.PT_STRING); EXPRCONSTANT arg = GetExprFactory().CreateStringConstant(name); EXPRTYPEOF arg2 = CreateTypeOf(CType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_PARAMETER, arg2, arg); } protected MethodSymbol GetPreDefMethod(PREDEFMETH pdm) { return GetSymbolLoader().getPredefinedMembers().GetMethod(pdm); } protected EXPRTYPEOF CreateTypeOf(CType CType) { return GetExprFactory().CreateTypeOf(CType); } protected EXPR CreateWraps(EXPRBOUNDLAMBDA anonmeth) { EXPR eXPR = null; for (Symbol symbol = anonmeth.ArgumentScope().firstChild; symbol != null; symbol = symbol.nextChild) { if (symbol.IsLocalVariableSymbol()) { LocalVariableSymbol localVariableSymbol = symbol.AsLocalVariableSymbol(); if (!localVariableSymbol.isThis) { EXPR pOptionalWrap = GenerateParameter(localVariableSymbol.name.Text, localVariableSymbol.GetType()); localVariableSymbol.wrap = GetExprFactory().CreateWrapNoAutoFree(anonmeth.OptionalBody.OptionalScopeSymbol, pOptionalWrap); EXPR eXPR2 = GetExprFactory().CreateSave(localVariableSymbol.wrap); eXPR = ((eXPR != null) ? GetExprFactory().CreateSequence(eXPR, eXPR2) : eXPR2); } } } return eXPR; } protected EXPR DestroyWraps(EXPRBOUNDLAMBDA anonmeth, EXPR sequence) { for (Symbol symbol = anonmeth.ArgumentScope(); symbol != null; symbol = symbol.nextChild) { if (symbol.IsLocalVariableSymbol()) { LocalVariableSymbol localVariableSymbol = symbol.AsLocalVariableSymbol(); if (!localVariableSymbol.isThis) { EXPR p = GetExprFactory().CreateWrap(anonmeth.OptionalBody.OptionalScopeSymbol, localVariableSymbol.wrap); sequence = GetExprFactory().CreateReverseSequence(sequence, p); } } } return sequence; } protected virtual EXPR GenerateConstructor(EXPRCALL expr) { if (IsDelegateConstructorCall(expr)) return GenerateDelegateConstructor(expr); EXPR arg = GetExprFactory().CreateMethodInfo(expr.mwi); EXPR args = GenerateArgsList(expr.GetOptionalArguments()); EXPR arg2 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); if (expr.type.IsAggregateType() && expr.type.AsAggregateType().getAggregate().IsAnonymousType()) { EXPR arg3 = GenerateMembersArray(expr.type.AsAggregateType(), PredefinedType.PT_METHODINFO); return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW_MEMBERS, arg, arg2, arg3); } return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW, arg, arg2); } protected virtual EXPR GenerateDelegateConstructor(EXPRCALL expr) { EXPRLIST eXPRLIST = expr.GetOptionalArguments().asLIST(); EXPR optionalElement = eXPRLIST.GetOptionalElement(); EXPRFUNCPTR eXPRFUNCPTR = eXPRLIST.GetOptionalNextListNode().asFUNCPTR(); MethodSymbol preDefMethod = GetPreDefMethod(PREDEFMETH.PM_METHODINFO_CREATEDELEGATE_TYPE_OBJECT); AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_DELEGATE, true); MethWithInst mwi = new MethWithInst(preDefMethod, optPredefTypeErr); EXPR arg = GenerateConstant(GetExprFactory().CreateMethodInfo(eXPRFUNCPTR.mwi)); EXPR arg2 = GetExprFactory().CreateMethodInfo(mwi); EXPR op = GenerateConstant(CreateTypeOf(expr.type)); EXPR op2 = Visit(optionalElement); EXPR args = GetExprFactory().CreateList(op, op2); EXPR arg3 = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION); EXPR arg4 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CALL, arg, arg2, arg3); EXPR arg5 = CreateTypeOf(expr.type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, arg4, arg5); } protected virtual EXPR GenerateArgsList(EXPR oldArgs) { EXPR first = null; EXPR last = first; ExpressionIterator expressionIterator = new ExpressionIterator(oldArgs); while (!expressionIterator.AtEnd()) { EXPR pExpr = expressionIterator.Current(); GetExprFactory().AppendItemToList(Visit(pExpr), ref first, ref last); expressionIterator.MoveNext(); } return first; } protected virtual EXPR GenerateIndexList(EXPR oldIndices) { CType reqPredefType = symbolLoader.GetReqPredefType(PredefinedType.PT_INT, true); EXPR first = null; EXPR last = first; ExpressionIterator expressionIterator = new ExpressionIterator(oldIndices); while (!expressionIterator.AtEnd()) { EXPR eXPR = expressionIterator.Current(); if (eXPR.type != reqPredefType) { EXPRCLASS pType = expressionFactory.CreateClass(reqPredefType, null, null); eXPR = expressionFactory.CreateCast(EXPRFLAG.EXF_LITERALCONST, pType, eXPR); eXPR.flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } EXPR newItem = Visit(eXPR); expressionFactory.AppendItemToList(newItem, ref first, ref last); expressionIterator.MoveNext(); } return first; } protected virtual EXPR GenerateConstant(EXPR expr) { EXPRFLAG nFlags = (EXPRFLAG)0; AggregateType reqPredefType = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT, true); if (expr.type.IsNullType()) { EXPRTYPEOF arg = CreateTypeOf(reqPredefType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, expr, arg); } AggregateType reqPredefType2 = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_STRING, true); if (expr.type != reqPredefType2) nFlags = EXPRFLAG.EXF_CTOR; EXPRCLASS pType = GetExprFactory().MakeClass(reqPredefType); EXPRCAST arg2 = GetExprFactory().CreateCast(nFlags, pType, expr); EXPRTYPEOF arg3 = CreateTypeOf(expr.type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, arg2, arg3); } protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); MethWithInst methWithInst = new MethWithInst(preDefMethod, optPredefTypeErr); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arg1, pMemberGroup, methWithInst); eXPRCALL.PredefinedMethod = pdm; return eXPRCALL; } protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1, EXPR arg2) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); EXPR pOptionalArguments = GetExprFactory().CreateList(arg1, arg2); MethWithInst methWithInst = new MethWithInst(preDefMethod, optPredefTypeErr); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst); eXPRCALL.PredefinedMethod = pdm; return eXPRCALL; } protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1, EXPR arg2, EXPR arg3) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); EXPR pOptionalArguments = GetExprFactory().CreateList(arg1, arg2, arg3); MethWithInst methWithInst = new MethWithInst(preDefMethod, optPredefTypeErr); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst); eXPRCALL.PredefinedMethod = pdm; return eXPRCALL; } protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1, EXPR arg2, EXPR arg3, EXPR arg4) { MethodSymbol preDefMethod = GetPreDefMethod(pdm); if (preDefMethod == null) return null; AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); EXPR pOptionalArguments = GetExprFactory().CreateList(arg1, arg2, arg3, arg4); MethWithInst methWithInst = new MethWithInst(preDefMethod, optPredefTypeErr); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst); eXPRCALL.PredefinedMethod = pdm; return eXPRCALL; } protected virtual EXPRARRINIT GenerateParamsArray(EXPR args, PredefinedType pt) { int num = ExpressionIterator.Count(args); AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(pt, true); ArrayType array = GetSymbolLoader().GetTypeManager().GetArray(optPredefTypeErr, 1); EXPRCONSTANT pOptionalArgumentDimensions = GetExprFactory().CreateIntegerConstant(num); EXPRARRINIT eXPRARRINIT = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, array, args, pOptionalArgumentDimensions, null); eXPRARRINIT.dimSize = num; eXPRARRINIT.dimSizes = new int[1] { eXPRARRINIT.dimSize }; return eXPRARRINIT; } protected virtual EXPRARRINIT GenerateMembersArray(AggregateType anonymousType, PredefinedType pt) { EXPR first = null; EXPR last = first; int num = 0; AggregateSymbol aggregate = anonymousType.getAggregate(); for (Symbol symbol = aggregate.firstChild; symbol != null; symbol = symbol.nextChild) { if (symbol.IsMethodSymbol()) { MethodSymbol methodSymbol = symbol.AsMethodSymbol(); if (methodSymbol.MethKind() == MethodKindEnum.PropAccessor) { EXPRMETHODINFO newItem = GetExprFactory().CreateMethodInfo(methodSymbol, anonymousType, methodSymbol.Params); GetExprFactory().AppendItemToList(newItem, ref first, ref last); num++; } } } AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(pt, true); ArrayType array = GetSymbolLoader().GetTypeManager().GetArray(optPredefTypeErr, 1); EXPRCONSTANT pOptionalArgumentDimensions = GetExprFactory().CreateIntegerConstant(num); EXPRARRINIT eXPRARRINIT = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, array, first, pOptionalArgumentDimensions, null); eXPRARRINIT.dimSize = num; eXPRARRINIT.dimSizes = new int[1] { eXPRARRINIT.dimSize }; return eXPRARRINIT; } protected void FixLiftedUserDefinedBinaryOperators(EXPRBINOP expr, ref EXPR pp1, ref EXPR pp2) { MethodSymbol methodSymbol = expr.GetUserDefinedCallMethod().Meth(); EXPR optionalLeftChild = expr.GetOptionalLeftChild(); EXPR optionalRightChild = expr.GetOptionalRightChild(); EXPR eXPR = pp1; EXPR eXPR2 = pp2; CType cType = methodSymbol.Params.Item(0); CType cType2 = methodSymbol.Params.Item(1); CType type = optionalLeftChild.type; CType type2 = optionalRightChild.type; if (!cType.IsNullableType() && !cType2.IsNullableType() && cType.IsAggregateType() && cType2.IsAggregateType() && cType.AsAggregateType().getAggregate().IsValueType() && cType2.AsAggregateType().getAggregate().IsValueType()) { CType nullable = GetSymbolLoader().GetTypeManager().GetNullable(cType); CType nullable2 = GetSymbolLoader().GetTypeManager().GetNullable(cType2); if (type.IsNullType() || (type == cType && (type2 == nullable2 || type2.IsNullType()))) eXPR = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR, CreateTypeOf(nullable)); if (type2.IsNullType() || (type2 == cType2 && (type == nullable || type.IsNullType()))) eXPR2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, eXPR2, CreateTypeOf(nullable2)); pp1 = eXPR; pp2 = eXPR2; } } protected bool IsNullableValueType(CType pType) { if (pType.IsNullableType()) { CType cType = pType.StripNubs(); if (cType.IsAggregateType()) return cType.AsAggregateType().getAggregate().IsValueType(); return false; } return false; } protected bool IsNullableValueAccess(EXPR pExpr, EXPR pObject) { if (pExpr.isPROP() && pExpr.asPROP().GetMemberGroup().GetOptionalObject() == pObject) return pObject.type.IsNullableType(); return false; } protected bool IsDelegateConstructorCall(EXPR pExpr) { if (!pExpr.isCALL()) return false; EXPRCALL eXPRCALL = pExpr.asCALL(); if (eXPRCALL.mwi.Meth() != null && eXPRCALL.mwi.Meth().IsConstructor() && eXPRCALL.type.isDelegateType() && eXPRCALL.GetOptionalArguments() != null && eXPRCALL.GetOptionalArguments().isLIST()) return eXPRCALL.GetOptionalArguments().asLIST().GetOptionalNextListNode() .kind == ExpressionKind.EK_FUNCPTR; return false; } private static bool isEnumToDecimalConversion(CType argtype, CType desttype) { CType cType = argtype.IsNullableType() ? argtype.StripNubs() : argtype; CType cType2 = desttype.IsNullableType() ? desttype.StripNubs() : desttype; if (cType.isEnumType()) return cType2.isPredefType(PredefinedType.PT_DECIMAL); return false; } } }