<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />

ExpressionTreeCallRewriter

using Microsoft.CSharp.RuntimeBinder.Semantics; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Microsoft.CSharp.RuntimeBinder { internal class ExpressionTreeCallRewriter : ExprVisitorBase { private class ExpressionEXPR : EXPR { public Expression Expression; public ExpressionEXPR(Expression e) { Expression = e; } } private Dictionary<EXPRCALL, Expression> _DictionaryOfParameters; private IEnumerable<Expression> _ListOfParameters; private TypeManager _typeManager; private int _currentParameterIndex; protected ExpressionTreeCallRewriter(TypeManager typeManager, IEnumerable<Expression> listOfParameters) { _typeManager = typeManager; _DictionaryOfParameters = new Dictionary<EXPRCALL, Expression>(); _ListOfParameters = listOfParameters; } public static Expression Rewrite(TypeManager typeManager, EXPR pExpr, IEnumerable<Expression> listOfParameters) { ExpressionTreeCallRewriter expressionTreeCallRewriter = new ExpressionTreeCallRewriter(typeManager, listOfParameters); expressionTreeCallRewriter.Visit(pExpr.asBIN().GetOptionalLeftChild()); EXPRCALL pExpr2 = pExpr.asBIN().GetOptionalRightChild().asCALL(); ExpressionEXPR expressionEXPR = expressionTreeCallRewriter.Visit(pExpr2) as ExpressionEXPR; return expressionEXPR.Expression; } protected override EXPR VisitSAVE(EXPRBINOP pExpr) { EXPRCALL eXPRCALL = pExpr.GetOptionalLeftChild().asCALL(); EXPRTYPEOF eXPRTYPEOF = eXPRCALL.GetOptionalArguments().asLIST().GetOptionalElement() .asTYPEOF(); Expression value = _ListOfParameters.ElementAt(_currentParameterIndex++); _DictionaryOfParameters.Add(eXPRCALL, value); return null; } protected override EXPR VisitCAST(EXPRCAST pExpr) { return base.VisitCAST(pExpr); } protected override EXPR VisitCALL(EXPRCALL pExpr) { if (pExpr.PredefinedMethod != 0) { switch (pExpr.PredefinedMethod) { case PREDEFMETH.PM_EXPRESSION_LAMBDA: return GenerateLambda(pExpr); case PREDEFMETH.PM_EXPRESSION_CALL: return GenerateCall(pExpr); case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX: case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2: return GenerateArrayIndex(pExpr); case PREDEFMETH.PM_EXPRESSION_CONVERT: case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED: case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED: return GenerateConvert(pExpr); case PREDEFMETH.PM_EXPRESSION_PROPERTY: return GenerateProperty(pExpr); case PREDEFMETH.PM_EXPRESSION_FIELD: return GenerateField(pExpr); case PREDEFMETH.PM_EXPRESSION_INVOKE: return GenerateInvoke(pExpr); case PREDEFMETH.PM_EXPRESSION_NEW: return GenerateNew(pExpr); case PREDEFMETH.PM_EXPRESSION_ADD: case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: case PREDEFMETH.PM_EXPRESSION_AND: case PREDEFMETH.PM_EXPRESSION_ANDALSO: case PREDEFMETH.PM_EXPRESSION_DIVIDE: case PREDEFMETH.PM_EXPRESSION_EQUAL: case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: case PREDEFMETH.PM_EXPRESSION_LESSTHAN: case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: case PREDEFMETH.PM_EXPRESSION_MODULO: case PREDEFMETH.PM_EXPRESSION_MULTIPLY: case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: case PREDEFMETH.PM_EXPRESSION_OR: case PREDEFMETH.PM_EXPRESSION_ORELSE: case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: case PREDEFMETH.PM_EXPRESSION_SUBTRACT: case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: return GenerateBinaryOperator(pExpr); case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: return GenerateUserDefinedBinaryOperator(pExpr); case PREDEFMETH.PM_EXPRESSION_NEGATE: case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: case PREDEFMETH.PM_EXPRESSION_NOT: return GenerateUnaryOperator(pExpr); case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: return GenerateUserDefinedUnaryOperator(pExpr); case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE: return GenerateConstantType(pExpr); case PREDEFMETH.PM_EXPRESSION_ASSIGN: return GenerateAssignment(pExpr); default: throw Error.InternalCompilerError(); } } return pExpr; } private ExpressionEXPR GenerateLambda(EXPRCALL pExpr) { ExpressionEXPR expressionEXPR = Visit(pExpr.GetOptionalArguments().asLIST().GetOptionalElement()) as ExpressionEXPR; Expression expression = expressionEXPR.Expression; return new ExpressionEXPR(expression); } private ExpressionEXPR GenerateCall(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); EXPRMETHODINFO methinfo; EXPRARRINIT arrinit; if (eXPRLIST.GetOptionalNextListNode().isLIST()) { methinfo = eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalElement() .asMETHODINFO(); arrinit = eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalNextListNode() .asARRINIT(); } else { methinfo = eXPRLIST.GetOptionalNextListNode().asMETHODINFO(); arrinit = null; } Expression instance = null; MethodInfo methodInfoFromExpr = GetMethodInfoFromExpr(methinfo); Expression[] argumentsFromArrayInit = GetArgumentsFromArrayInit(arrinit); if ((object)methodInfoFromExpr == null) throw Error.InternalCompilerError(); if (!methodInfoFromExpr.IsStatic) instance = GetExpression(pExpr.GetOptionalArguments().asLIST().GetOptionalElement()); return new ExpressionEXPR(Expression.Call(instance, methodInfoFromExpr, argumentsFromArrayInit)); } private ExpressionEXPR GenerateArrayIndex(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); Expression expression = GetExpression(eXPRLIST.GetOptionalElement()); Expression[] indexes = (pExpr.PredefinedMethod != PREDEFMETH.PM_EXPRESSION_ARRAYINDEX) ? GetArgumentsFromArrayInit(eXPRLIST.GetOptionalNextListNode().asARRINIT()) : new Expression[1] { GetExpression(eXPRLIST.GetOptionalNextListNode()) }; return new ExpressionEXPR(Expression.ArrayAccess(expression, indexes)); } private ExpressionEXPR GenerateConvert(EXPRCALL pExpr) { PREDEFMETH predefinedMethod = pExpr.PredefinedMethod; Expression expression; Type associatedSystemType; if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED || predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED) { EXPRLIST eXPRLIST = pExpr.asCALL().GetOptionalArguments().asLIST(); EXPRLIST eXPRLIST2 = eXPRLIST.GetOptionalNextListNode().asLIST(); expression = GetExpression(eXPRLIST.GetOptionalElement()); associatedSystemType = eXPRLIST2.GetOptionalElement().asTYPEOF().SourceType.type.AssociatedSystemType; if ((object)expression.Type.MakeByRefType() == associatedSystemType) return new ExpressionEXPR(expression); MethodInfo methodInfoFromExpr = GetMethodInfoFromExpr(eXPRLIST2.GetOptionalNextListNode().asMETHODINFO()); if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED) return new ExpressionEXPR(Expression.Convert(expression, associatedSystemType, methodInfoFromExpr)); return new ExpressionEXPR(Expression.ConvertChecked(expression, associatedSystemType, methodInfoFromExpr)); } EXPRLIST eXPRLIST3 = pExpr.asCALL().GetOptionalArguments().asLIST(); expression = GetExpression(eXPRLIST3.GetOptionalElement()); associatedSystemType = eXPRLIST3.GetOptionalNextListNode().asTYPEOF().SourceType.type.AssociatedSystemType; if ((object)expression.Type.MakeByRefType() == associatedSystemType) return new ExpressionEXPR(expression); if ((pExpr.flags & EXPRFLAG.EXF_USERCALLABLE) != 0) return new ExpressionEXPR(Expression.Unbox(expression, associatedSystemType)); if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT) return new ExpressionEXPR(Expression.Convert(expression, associatedSystemType)); return new ExpressionEXPR(Expression.ConvertChecked(expression, associatedSystemType)); } private ExpressionEXPR GenerateProperty(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.asCALL().GetOptionalArguments().asLIST(); EXPR optionalElement = eXPRLIST.GetOptionalElement(); EXPRPropertyInfo propinfo = eXPRLIST.GetOptionalNextListNode().isLIST() ? eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalElement() .asPropertyInfo() : eXPRLIST.GetOptionalNextListNode().asPropertyInfo(); EXPRARRINIT eXPRARRINIT = eXPRLIST.GetOptionalNextListNode().isLIST() ? eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalNextListNode() .asARRINIT() : null; PropertyInfo propertyInfoFromExpr = GetPropertyInfoFromExpr(propinfo); if ((object)propertyInfoFromExpr == null) throw Error.InternalCompilerError(); if (eXPRARRINIT == null) return new ExpressionEXPR(Expression.Property(GetExpression(optionalElement), propertyInfoFromExpr)); return new ExpressionEXPR(Expression.Property(GetExpression(optionalElement), propertyInfoFromExpr, GetArgumentsFromArrayInit(eXPRARRINIT))); } private ExpressionEXPR GenerateField(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.asCALL().GetOptionalArguments().asLIST(); Type type = eXPRLIST.GetOptionalNextListNode().asFIELDINFO().FieldType() .AssociatedSystemType; FieldInfo fieldInfo = eXPRLIST.GetOptionalNextListNode().asFIELDINFO().Field() .AssociatedFieldInfo; if (!type.GetTypeInfo().get_IsGenericType() && !type.GetTypeInfo().get_IsNested()) type = fieldInfo.DeclaringType; if (type.GetTypeInfo().get_IsGenericType()) fieldInfo = TypeExtensions.GetField(type, fieldInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return new ExpressionEXPR(Expression.Field(GetExpression(eXPRLIST.GetOptionalElement()), fieldInfo)); } private ExpressionEXPR GenerateInvoke(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.asCALL().GetOptionalArguments().asLIST(); return new ExpressionEXPR(Expression.Invoke(GetExpression(eXPRLIST.GetOptionalElement()), GetArgumentsFromArrayInit(eXPRLIST.GetOptionalNextListNode().asARRINIT()))); } private ExpressionEXPR GenerateNew(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.asCALL().GetOptionalArguments().asLIST(); ConstructorInfo constructorInfoFromExpr = GetConstructorInfoFromExpr(eXPRLIST.GetOptionalElement().asMETHODINFO()); Expression[] argumentsFromArrayInit = GetArgumentsFromArrayInit(eXPRLIST.GetOptionalNextListNode().asARRINIT()); return new ExpressionEXPR(Expression.New(constructorInfoFromExpr, argumentsFromArrayInit)); } private ExpressionEXPR GenerateConstantType(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); return new ExpressionEXPR(Expression.Constant(GetObject(eXPRLIST.GetOptionalElement()), eXPRLIST.GetOptionalNextListNode().asTYPEOF().SourceType.type.AssociatedSystemType)); } private ExpressionEXPR GenerateAssignment(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); return new ExpressionEXPR(Expression.Assign(GetExpression(eXPRLIST.GetOptionalElement()), GetExpression(eXPRLIST.GetOptionalNextListNode()))); } private ExpressionEXPR GenerateBinaryOperator(EXPRCALL pExpr) { Expression expression = GetExpression(pExpr.GetOptionalArguments().asLIST().GetOptionalElement()); Expression expression2 = GetExpression(pExpr.GetOptionalArguments().asLIST().GetOptionalNextListNode()); switch (pExpr.PredefinedMethod) { case PREDEFMETH.PM_EXPRESSION_ADD: return new ExpressionEXPR(Expression.Add(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_AND: return new ExpressionEXPR(Expression.And(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_DIVIDE: return new ExpressionEXPR(Expression.Divide(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_EQUAL: return new ExpressionEXPR(Expression.Equal(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: return new ExpressionEXPR(Expression.ExclusiveOr(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: return new ExpressionEXPR(Expression.GreaterThan(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: return new ExpressionEXPR(Expression.GreaterThanOrEqual(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: return new ExpressionEXPR(Expression.LeftShift(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_LESSTHAN: return new ExpressionEXPR(Expression.LessThan(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: return new ExpressionEXPR(Expression.LessThanOrEqual(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_MODULO: return new ExpressionEXPR(Expression.Modulo(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_MULTIPLY: return new ExpressionEXPR(Expression.Multiply(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: return new ExpressionEXPR(Expression.NotEqual(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_OR: return new ExpressionEXPR(Expression.Or(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: return new ExpressionEXPR(Expression.RightShift(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_SUBTRACT: return new ExpressionEXPR(Expression.Subtract(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_ORELSE: return new ExpressionEXPR(Expression.OrElse(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_ANDALSO: return new ExpressionEXPR(Expression.AndAlso(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: return new ExpressionEXPR(Expression.AddChecked(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: return new ExpressionEXPR(Expression.MultiplyChecked(expression, expression2)); case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: return new ExpressionEXPR(Expression.SubtractChecked(expression, expression2)); default: throw Error.InternalCompilerError(); } } private ExpressionEXPR GenerateUserDefinedBinaryOperator(EXPRCALL pExpr) { EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); Expression expression = GetExpression(eXPRLIST.GetOptionalElement()); Expression expression2 = GetExpression(eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalElement()); eXPRLIST = eXPRLIST.GetOptionalNextListNode().asLIST(); bool liftToNull = false; MethodInfo methodInfoFromExpr; if (eXPRLIST.GetOptionalNextListNode().isLIST()) { EXPRCONSTANT eXPRCONSTANT = eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalElement() .asCONSTANT(); liftToNull = (eXPRCONSTANT.getVal().iVal == 1); methodInfoFromExpr = GetMethodInfoFromExpr(eXPRLIST.GetOptionalNextListNode().asLIST().GetOptionalNextListNode() .asMETHODINFO()); } else methodInfoFromExpr = GetMethodInfoFromExpr(eXPRLIST.GetOptionalNextListNode().asMETHODINFO()); switch (pExpr.PredefinedMethod) { case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: return new ExpressionEXPR(Expression.Add(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: return new ExpressionEXPR(Expression.And(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: return new ExpressionEXPR(Expression.Divide(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: return new ExpressionEXPR(Expression.Equal(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: return new ExpressionEXPR(Expression.ExclusiveOr(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: return new ExpressionEXPR(Expression.GreaterThan(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: return new ExpressionEXPR(Expression.GreaterThanOrEqual(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: return new ExpressionEXPR(Expression.LeftShift(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: return new ExpressionEXPR(Expression.LessThan(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: return new ExpressionEXPR(Expression.LessThanOrEqual(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: return new ExpressionEXPR(Expression.Modulo(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: return new ExpressionEXPR(Expression.Multiply(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: return new ExpressionEXPR(Expression.NotEqual(expression, expression2, liftToNull, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: return new ExpressionEXPR(Expression.Or(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: return new ExpressionEXPR(Expression.RightShift(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: return new ExpressionEXPR(Expression.Subtract(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: return new ExpressionEXPR(Expression.OrElse(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: return new ExpressionEXPR(Expression.AndAlso(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: return new ExpressionEXPR(Expression.AddChecked(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: return new ExpressionEXPR(Expression.MultiplyChecked(expression, expression2, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: return new ExpressionEXPR(Expression.SubtractChecked(expression, expression2, methodInfoFromExpr)); default: throw Error.InternalCompilerError(); } } private ExpressionEXPR GenerateUnaryOperator(EXPRCALL pExpr) { PREDEFMETH predefinedMethod = pExpr.PredefinedMethod; Expression expression = GetExpression(pExpr.GetOptionalArguments()); switch (predefinedMethod) { case PREDEFMETH.PM_EXPRESSION_NOT: return new ExpressionEXPR(Expression.Not(expression)); case PREDEFMETH.PM_EXPRESSION_NEGATE: return new ExpressionEXPR(Expression.Negate(expression)); case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: return new ExpressionEXPR(Expression.NegateChecked(expression)); default: throw Error.InternalCompilerError(); } } private ExpressionEXPR GenerateUserDefinedUnaryOperator(EXPRCALL pExpr) { PREDEFMETH predefinedMethod = pExpr.PredefinedMethod; EXPRLIST eXPRLIST = pExpr.GetOptionalArguments().asLIST(); Expression expression = GetExpression(eXPRLIST.GetOptionalElement()); MethodInfo methodInfoFromExpr = GetMethodInfoFromExpr(eXPRLIST.GetOptionalNextListNode().asMETHODINFO()); switch (predefinedMethod) { case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: return new ExpressionEXPR(Expression.Not(expression, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: return new ExpressionEXPR(Expression.Negate(expression, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: return new ExpressionEXPR(Expression.UnaryPlus(expression, methodInfoFromExpr)); case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: return new ExpressionEXPR(Expression.NegateChecked(expression, methodInfoFromExpr)); default: throw Error.InternalCompilerError(); } } private Expression GetExpression(EXPR pExpr) { if (pExpr.isWRAP()) return _DictionaryOfParameters[pExpr.asWRAP().GetOptionalExpression().asCALL()]; if (!pExpr.isCONSTANT()) { EXPRCALL eXPRCALL = pExpr.asCALL(); switch (eXPRCALL.PredefinedMethod) { case PREDEFMETH.PM_EXPRESSION_CALL: return GenerateCall(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_CONVERT: case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED: case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED: return GenerateConvert(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT: { EXPRLIST eXPRLIST = eXPRCALL.GetOptionalArguments().asLIST(); return Expression.NewArrayInit(eXPRLIST.GetOptionalElement().asTYPEOF().SourceType.type.AssociatedSystemType, GetArgumentsFromArrayInit(eXPRLIST.GetOptionalNextListNode().asARRINIT())); } case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX: case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2: return GenerateArrayIndex(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_NEW: return GenerateNew(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_PROPERTY: return GenerateProperty(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_FIELD: return GenerateField(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE: return GenerateConstantType(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_ASSIGN: return GenerateAssignment(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_ADD: case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: case PREDEFMETH.PM_EXPRESSION_AND: case PREDEFMETH.PM_EXPRESSION_ANDALSO: case PREDEFMETH.PM_EXPRESSION_DIVIDE: case PREDEFMETH.PM_EXPRESSION_EQUAL: case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: case PREDEFMETH.PM_EXPRESSION_LESSTHAN: case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: case PREDEFMETH.PM_EXPRESSION_MODULO: case PREDEFMETH.PM_EXPRESSION_MULTIPLY: case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: case PREDEFMETH.PM_EXPRESSION_OR: case PREDEFMETH.PM_EXPRESSION_ORELSE: case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: case PREDEFMETH.PM_EXPRESSION_SUBTRACT: case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: return GenerateBinaryOperator(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: return GenerateUserDefinedBinaryOperator(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_NEGATE: case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: case PREDEFMETH.PM_EXPRESSION_NOT: return GenerateUnaryOperator(eXPRCALL).Expression; case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: return GenerateUserDefinedUnaryOperator(eXPRCALL).Expression; default: throw Error.InternalCompilerError(); } } return null; } private object GetObject(EXPR pExpr) { if (pExpr.isCAST()) return GetObject(pExpr.asCAST().GetArgument()); if (pExpr.isTYPEOF()) return pExpr.asTYPEOF().SourceType.type.AssociatedSystemType; if (pExpr.isMETHODINFO()) return GetMethodInfoFromExpr(pExpr.asMETHODINFO()); if (pExpr.isCONSTANT()) { CONSTVAL val = pExpr.asCONSTANT().Val; CType cType = pExpr.type; if (pExpr.type.IsNullType()) return null; if (pExpr.type.isEnumType()) cType = cType.getAggregate().GetUnderlyingType(); object obj; switch (cType.AssociatedSystemType.GetTypeCode()) { case TypeCode.Boolean: obj = val.boolVal; break; case TypeCode.SByte: obj = val.sbyteVal; break; case TypeCode.Byte: obj = val.byteVal; break; case TypeCode.Int16: obj = val.shortVal; break; case TypeCode.UInt16: obj = val.ushortVal; break; case TypeCode.Int32: obj = val.iVal; break; case TypeCode.UInt32: obj = val.uiVal; break; case TypeCode.Int64: obj = val.longVal; break; case TypeCode.UInt64: obj = val.ulongVal; break; case TypeCode.Single: obj = val.floatVal; break; case TypeCode.Double: obj = val.doubleVal; break; case TypeCode.Decimal: obj = val.decVal; break; case TypeCode.Char: obj = val.cVal; break; case TypeCode.String: obj = val.strVal; break; default: obj = val.objectVal; break; } if (pExpr.type.isEnumType()) obj = Enum.ToObject(pExpr.type.AssociatedSystemType, obj); return obj; } if (pExpr.isZEROINIT()) { if (pExpr.asZEROINIT().OptionalArgument != null) return GetObject(pExpr.asZEROINIT().OptionalArgument); return Activator.CreateInstance(pExpr.type.AssociatedSystemType); } throw Error.InternalCompilerError(); } private Expression[] GetArgumentsFromArrayInit(EXPRARRINIT arrinit) { List<Expression> list = new List<Expression>(); if (arrinit != null) { EXPR eXPR = arrinit.GetOptionalArguments(); EXPR eXPR2 = eXPR; while (eXPR != null) { if (eXPR.isLIST()) { eXPR2 = eXPR.asLIST().GetOptionalElement(); eXPR = eXPR.asLIST().GetOptionalNextListNode(); } else { eXPR2 = eXPR; eXPR = null; } list.Add(GetExpression(eXPR2)); } } return list.ToArray(); } private MethodInfo GetMethodInfoFromExpr(EXPRMETHODINFO methinfo) { AggregateType ats = methinfo.Method.Ats; MethodSymbol methodSymbol = methinfo.Method.Meth(); TypeArray typeArray = _typeManager.SubstTypeArray(methodSymbol.Params, ats, methodSymbol.typeVars); CType cType = _typeManager.SubstType(methodSymbol.RetType, ats, methodSymbol.typeVars); Type type = ats.AssociatedSystemType; MethodInfo methodInfo = methodSymbol.AssociatedMemberInfo as MethodInfo; if (!type.GetTypeInfo().get_IsGenericType() && !type.IsNested) type = methodInfo.DeclaringType; foreach (MethodInfo runtimeMethod in type.GetRuntimeMethods()) { if (RuntimeBinderExtensions.HasSameMetadataDefinitionAs(runtimeMethod, methodInfo)) { bool flag = true; ParameterInfo[] parameters = runtimeMethod.GetParameters(); for (int i = 0; i < typeArray.size; i++) { if (!TypesAreEqual(parameters[i].ParameterType, typeArray.Item(i).AssociatedSystemType)) { flag = false; break; } } if (flag) { if (!runtimeMethod.IsGenericMethod) return runtimeMethod; int num = (methinfo.Method.TypeArgs != null) ? methinfo.Method.TypeArgs.size : 0; Type[] array = new Type[num]; if (num > 0) { for (int j = 0; j < methinfo.Method.TypeArgs.size; j++) { array[j] = methinfo.Method.TypeArgs[j].AssociatedSystemType; } } return runtimeMethod.MakeGenericMethod(array); } } } throw Error.InternalCompilerError(); } private ConstructorInfo GetConstructorInfoFromExpr(EXPRMETHODINFO methinfo) { AggregateType ats = methinfo.Method.Ats; MethodSymbol methodSymbol = methinfo.Method.Meth(); TypeArray typeArray = _typeManager.SubstTypeArray(methodSymbol.Params, ats); Type type = ats.AssociatedSystemType; ConstructorInfo constructorInfo = (ConstructorInfo)methodSymbol.AssociatedMemberInfo; if (!type.GetTypeInfo().get_IsGenericType() && !type.IsNested) type = constructorInfo.DeclaringType; ConstructorInfo[] constructors = TypeExtensions.GetConstructors(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo constructorInfo2 in constructors) { if (RuntimeBinderExtensions.HasSameMetadataDefinitionAs(constructorInfo2, constructorInfo)) { bool flag = true; ParameterInfo[] parameters = constructorInfo2.GetParameters(); for (int j = 0; j < typeArray.size; j++) { if (!TypesAreEqual(parameters[j].ParameterType, typeArray.Item(j).AssociatedSystemType)) { flag = false; break; } } if (flag) return constructorInfo2; } } throw Error.InternalCompilerError(); } private PropertyInfo GetPropertyInfoFromExpr(EXPRPropertyInfo propinfo) { AggregateType ats = propinfo.Property.Ats; PropertySymbol propertySymbol = propinfo.Property.Prop(); TypeArray typeArray = _typeManager.SubstTypeArray(propertySymbol.Params, ats, null); CType cType = _typeManager.SubstType(propertySymbol.RetType, ats, null); Type type = ats.AssociatedSystemType; PropertyInfo associatedPropertyInfo = propertySymbol.AssociatedPropertyInfo; if (!type.GetTypeInfo().get_IsGenericType() && !type.IsNested) type = associatedPropertyInfo.DeclaringType; PropertyInfo[] properties = TypeExtensions.GetProperties(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (RuntimeBinderExtensions.HasSameMetadataDefinitionAs(propertyInfo, associatedPropertyInfo)) { bool flag = true; ParameterInfo[] array = ((object)PropertyInfoExtensions.GetSetMethod(propertyInfo, true) != null) ? PropertyInfoExtensions.GetSetMethod(propertyInfo, true).GetParameters() : PropertyInfoExtensions.GetGetMethod(propertyInfo, true).GetParameters(); for (int j = 0; j < typeArray.size; j++) { if (!TypesAreEqual(array[j].ParameterType, typeArray.Item(j).AssociatedSystemType)) { flag = false; break; } } if (flag) return propertyInfo; } } throw Error.InternalCompilerError(); } private bool TypesAreEqual(Type t1, Type t2) { if ((object)t1 == t2) return true; return RuntimeBinderExtensions.IsEquivalentTo(t1, t2); } } }