ExpressionTreeRewriter
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal sealed class ExpressionTreeRewriter : ExprVisitorBase
{
private ExprFactory expressionFactory;
private SymbolLoader symbolLoader;
private ExprBoundLambda currentAnonMeth;
private 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);
}
private ExprFactory GetExprFactory()
{
return expressionFactory;
}
private SymbolLoader GetSymbolLoader()
{
return symbolLoader;
}
private ExpressionTreeRewriter(ExprFactory expressionFactory, SymbolLoader symbolLoader)
{
this.expressionFactory = expressionFactory;
this.symbolLoader = symbolLoader;
alwaysRewrite = false;
}
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 = GetExprFactory().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);
}
protected override Expr VisitBOUNDLAMBDA(ExprBoundLambda anonmeth)
{
ExprBoundLambda exprBoundLambda = currentAnonMeth;
currentAnonMeth = anonmeth;
MethodSymbol preDefMethod = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA);
CType delegateType = anonmeth.DelegateType;
TypeArray typeArgs = GetSymbolLoader().getBSymmgr().AllocParams(1, new CType[1] {
delegateType
});
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);
ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst);
ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, pType, pOptionalArguments, pMemberGroup, methWithInst);
Expr expr2 = exprCall;
exprCall.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 VisitFIELD(ExprField expr)
{
Expr arg = (expr.OptionalObject != null) ? Visit(expr.OptionalObject) : GetExprFactory().CreateNull();
ExprFieldInfo arg2 = GetExprFactory().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 || 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 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 = 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.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 VisitARRAYLENGTH(ExprArrayLength pExpr)
{
return GenerateBuiltInUnaryOperator(PREDEFMETH.PM_EXPRESSION_ARRAYLENGTH, pExpr.Array, pExpr);
}
protected override Expr VisitQUESTIONMARK(ExprQuestionMark pExpr)
{
Expr arg = Visit(pExpr.TestExpression);
Expr arg2 = GenerateQuestionMarkOperand(pExpr.Consequence.OptionalLeftChild);
Expr arg3 = GenerateQuestionMarkOperand(pExpr.Consequence.OptionalRightChild);
return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONDITION, arg, arg2, arg3);
}
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 = GetExprFactory().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 = GetExprFactory().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) : GetExprFactory().CreateNull();
Expr arg2 = GetExprFactory().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(expr.Type.AsArrayType().GetElementType());
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)
{
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);
}
private Expr GenerateQuestionMarkOperand(Expr pExpr)
{
ExprCast exprCast;
if ((exprCast = (pExpr as ExprCast)) != null)
return GenerateConversion(exprCast.Argument, pExpr.Type, pExpr.isChecked());
return Visit(pExpr);
}
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;
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)
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 GenerateBuiltInUnaryOperator(pdm, child, expr);
}
private 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;
}
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 = GetExprFactory().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;
PREDEFMETH pdm;
switch (expr.Kind) {
case ExpressionKind.True:
case ExpressionKind.False:
return Visit(exprCall);
case ExpressionKind.UnaryPlus:
pdm = PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED;
break;
case ExpressionKind.BitwiseNot:
pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED;
break;
case ExpressionKind.LogicalNot:
pdm = PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED;
break;
case ExpressionKind.Negate:
case ExpressionKind.DecimalNegate:
pdm = (expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED);
break;
case ExpressionKind.Inc:
case ExpressionKind.Dec:
case ExpressionKind.DecimalInc:
case ExpressionKind.DecimalDec:
pdm = PREDEFMETH.PM_EXPRESSION_CALL;
break;
default:
throw Error.InternalCompilerError();
}
Expr expr2 = Visit(pExpr);
Expr arg = GetExprFactory().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 = GetExprFactory().CreateBoolConstant(false);
Expr arg2 = GetExprFactory().CreateMethodInfo(expr.UserDefinedCallMethod);
return GenerateCall(pdm, pp, pp2, arg, arg2);
}
private Expr RewriteLambdaBody(ExprBoundLambda anonmeth)
{
ExprBlock optionalBody = anonmeth.OptionalBody;
ExprReturn exprReturn;
if ((exprReturn = (optionalBody.OptionalStatements as ExprReturn)) != null)
return Visit(exprReturn.OptionalObject);
throw Error.InternalCompilerError();
}
private 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);
}
private Expr GenerateConversion(Expr arg, CType CType, bool bChecked)
{
return GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked());
}
private 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 cType = pArgument.Type.StripNubs();
Expr arg = CreateTypeOf(cType);
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 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);
}
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 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);
}
private MethodSymbol GetPreDefMethod(PREDEFMETH pdm)
{
return GetSymbolLoader().getPredefinedMembers().GetMethod(pdm);
}
private ExprTypeOf CreateTypeOf(CType CType)
{
return GetExprFactory().CreateTypeOf(CType);
}
private 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;
}
private 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;
}
private Expr GenerateConstructor(ExprCall expr)
{
if (IsDelegateConstructorCall(expr))
return GenerateDelegateConstructor(expr);
Expr arg = GetExprFactory().CreateMethodInfo(expr.MethWithInst);
Expr args = GenerateArgsList(expr.OptionalArguments);
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);
}
private Expr GenerateDelegateConstructor(ExprCall expr)
{
ExprList exprList = (ExprList)expr.OptionalArguments;
Expr optionalElement = exprList.OptionalElement;
ExprFuncPtr exprFuncPtr = (ExprFuncPtr)exprList.OptionalNextListNode;
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.MethWithInst));
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);
}
private 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;
}
private 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);
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;
}
private 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);
}
private 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);
ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst);
ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, arg1, pMemberGroup, methWithInst);
exprCall.PredefinedMethod = pdm;
return exprCall;
}
private 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);
ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst);
ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst);
exprCall.PredefinedMethod = pdm;
return exprCall;
}
private 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);
ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst);
ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst);
exprCall.PredefinedMethod = pdm;
return exprCall;
}
private 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);
ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, methWithInst);
ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, methWithInst.Meth().RetType, pOptionalArguments, pMemberGroup, methWithInst);
exprCall.PredefinedMethod = pdm;
return exprCall;
}
private ExprArrayInit GenerateParamsArray(Expr args, PredefinedType pt)
{
int num = ExpressionIterator.Count(args);
AggregateType optPredefTypeErr = GetSymbolLoader().GetOptPredefTypeErr(pt, true);
ArrayType array = GetSymbolLoader().GetTypeManager().GetArray(optPredefTypeErr, 1, true);
ExprConstant pOptionalArgumentDimensions = GetExprFactory().CreateIntegerConstant(num);
ExprArrayInit exprArrayInit = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, array, args, pOptionalArgumentDimensions, null);
exprArrayInit.DimensionSize = num;
exprArrayInit.DimensionSizes = new int[1] {
exprArrayInit.DimensionSize
};
return exprArrayInit;
}
private ExprArrayInit 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, true);
ExprConstant pOptionalArgumentDimensions = GetExprFactory().CreateIntegerConstant(num);
ExprArrayInit exprArrayInit = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, array, first, pOptionalArgumentDimensions, null);
exprArrayInit.DimensionSize = num;
exprArrayInit.DimensionSizes = new int[1] {
exprArrayInit.DimensionSize
};
return exprArrayInit;
}
private 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;
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())))
expr2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr2, CreateTypeOf(nullable));
if (type2.IsNullType() || (type2 == cType2 && (type == nullable || type.IsNullType())))
expr3 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, expr3, CreateTypeOf(nullable2));
pp1 = expr2;
pp2 = expr3;
}
}
private bool IsNullableValueType(CType pType)
{
if (pType.IsNullableType()) {
CType cType = pType.StripNubs();
if (cType.IsAggregateType())
return cType.AsAggregateType().getAggregate().IsValueType();
return false;
}
return false;
}
private bool IsNullableValueAccess(Expr pExpr, Expr pObject)
{
ExprProperty exprProperty;
if ((exprProperty = (pExpr as ExprProperty)) != null && exprProperty.MemberGroup.OptionalObject == pObject)
return pObject.Type.IsNullableType();
return false;
}
private bool IsDelegateConstructorCall(Expr pExpr)
{
ExprCall exprCall;
if ((exprCall = (pExpr as ExprCall)) == null)
return false;
ExprList exprList;
if (exprCall.MethWithInst.Meth() != null && exprCall.MethWithInst.Meth().IsConstructor() && exprCall.Type.isDelegateType() && exprCall.OptionalArguments != null && (exprList = (exprCall.OptionalArguments as ExprList)) != null)
return exprList.OptionalNextListNode.Kind == ExpressionKind.FunctionPointer;
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;
}
}
}