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