@@ -2000,6 +2000,7 @@ public static bool TryEmit(Expression expr,
20002000#endif
20012001 ILGenerator il, ref ClosureInfo closure, CompilerFlags setup, ParentFlags parent, int byRefIndex = -1)
20022002 {
2003+ var exprType = expr.Type;
20032004 while (true)
20042005 {
20052006 closure.LastEmitIsAddress = false;
@@ -2041,7 +2042,7 @@ public static bool TryEmit(Expression expr,
20412042 var arrIndexExpr = (BinaryExpression)expr;
20422043 return TryEmit(arrIndexExpr.Left, paramExprs, il, ref closure, setup, parent | ParentFlags.IndexAccess)
20432044 && TryEmit(arrIndexExpr.Right, paramExprs, il, ref closure, setup, parent | ParentFlags.IndexAccess) // #265
2044- && TryEmitArrayIndexGet(il, expr.Type , ref closure, parent);
2045+ && TryEmitArrayIndexGet(il, exprType , ref closure, parent);
20452046
20462047 case ExpressionType.ArrayLength:
20472048 if (!TryEmit(((UnaryExpression)expr).Operand, paramExprs, il, ref closure, setup, parent))
@@ -2052,7 +2053,7 @@ public static bool TryEmit(Expression expr,
20522053
20532054 case ExpressionType.Constant:
20542055 return (parent & ParentFlags.IgnoreResult) != 0 ||
2055- TryEmitConstant((ConstantExpression)expr, expr.Type , il, ref closure, byRefIndex);
2056+ TryEmitConstant((ConstantExpression)expr, exprType , il, ref closure, byRefIndex);
20562057
20572058 case ExpressionType.Call:
20582059 return TryEmitMethodCall(expr, paramExprs, il, ref closure, setup, parent, byRefIndex);
@@ -2087,15 +2088,15 @@ public static bool TryEmit(Expression expr,
20872088 case ExpressionType.LessThanOrEqual:
20882089 case ExpressionType.Equal:
20892090 case ExpressionType.NotEqual:
2090- if ((setup & CompilerFlags.DisableInterpreter) == 0 && expr.Type .IsPrimitive &&
2091+ if ((setup & CompilerFlags.DisableInterpreter) == 0 && exprType .IsPrimitive &&
20912092 Interpreter.TryInterpretBoolean(out var boolResult, expr))
20922093 {
20932094 if ((parent & ParentFlags.IgnoreResult) == 0)
20942095 il.Demit(boolResult ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
20952096 return true;
20962097 }
2097- var binaryExpr = ( BinaryExpression)expr;
2098- return TryEmitComparison(binaryExpr.Left, binaryExpr.Right, expr.Type, nodeType, paramExprs, il, ref closure, setup, parent);
2098+ return TryEmitComparison(((BinaryExpression)expr).Left, (( BinaryExpression)expr).Right, exprType, nodeType, paramExprs, il,
2099+ ref closure, setup, parent);
20992100
21002101 case ExpressionType.Add:
21012102 case ExpressionType.AddChecked:
@@ -2105,14 +2106,25 @@ public static bool TryEmit(Expression expr,
21052106 case ExpressionType.MultiplyChecked:
21062107 case ExpressionType.Divide:
21072108 case ExpressionType.Modulo:
2109+ if ((setup & CompilerFlags.DisableInterpreter) == 0 && exprType.IsPrimitive &&
2110+ Interpreter.TryInterpret(out var resultObj, expr))
2111+ {
2112+ if ((parent & ParentFlags.IgnoreResult) == 0)
2113+ TryEmitPrimitiveOrEnumOrDecimalConstant(il, resultObj, exprType);
2114+ return true;
2115+ }
2116+ return TryEmitArithmetic(((BinaryExpression)expr).Left, ((BinaryExpression)expr).Right, nodeType, exprType, paramExprs, il,
2117+ ref closure, setup, parent);
2118+
21082119 case ExpressionType.Power:
21092120 case ExpressionType.And:
21102121 case ExpressionType.Or:
21112122 case ExpressionType.ExclusiveOr:
21122123 case ExpressionType.LeftShift:
21132124 case ExpressionType.RightShift:
2114- // todo: @wip interpreter
2115- return TryEmitArithmetic(((BinaryExpression)expr).Left, ((BinaryExpression)expr).Right, nodeType, expr.Type, paramExprs, il, ref closure, setup, parent);
2125+ // todo: @wip #468 add interpretation when those node types are supported
2126+ return TryEmitArithmetic(((BinaryExpression)expr).Left, ((BinaryExpression)expr).Right, nodeType, exprType, paramExprs, il,
2127+ ref closure, setup, parent);
21162128
21172129 case ExpressionType.AndAlso:
21182130 case ExpressionType.OrElse:
@@ -2128,12 +2140,12 @@ public static bool TryEmit(Expression expr,
21282140
21292141 case ExpressionType.PostIncrementAssign:
21302142 case ExpressionType.PreIncrementAssign:
2131- return TryEmitArithmeticAndOrAssign(((UnaryExpression)expr).Operand, null, expr.Type , ExpressionType.Add,
2143+ return TryEmitArithmeticAndOrAssign(((UnaryExpression)expr).Operand, null, exprType , ExpressionType.Add,
21322144 nodeType == ExpressionType.PostIncrementAssign, paramExprs, il, ref closure, setup, parent);
21332145
21342146 case ExpressionType.PostDecrementAssign:
21352147 case ExpressionType.PreDecrementAssign:
2136- return TryEmitArithmeticAndOrAssign(((UnaryExpression)expr).Operand, null, expr.Type , ExpressionType.Subtract,
2148+ return TryEmitArithmeticAndOrAssign(((UnaryExpression)expr).Operand, null, exprType , ExpressionType.Subtract,
21372149 nodeType == ExpressionType.PostDecrementAssign, paramExprs, il, ref closure, setup, parent);
21382150
21392151 case ExpressionType.AddAssign:
@@ -2152,7 +2164,7 @@ public static bool TryEmit(Expression expr,
21522164 case ExpressionType.RightShiftAssign:
21532165 case ExpressionType.Assign:
21542166 var ba = (BinaryExpression)expr;
2155- return TryEmitArithmeticAndOrAssign(ba.Left, ba.Right, expr.Type ,
2167+ return TryEmitArithmeticAndOrAssign(ba.Left, ba.Right, exprType ,
21562168 AssignToArithmeticOrSelf(nodeType), false, paramExprs, il, ref closure, setup, parent);
21572169
21582170 case ExpressionType.Block:
@@ -2293,8 +2305,8 @@ public static bool TryEmit(Expression expr,
22932305 }
22942306
22952307 case ExpressionType.Default:
2296- if (expr.Type != typeof(void) && (parent & ParentFlags.IgnoreResult) == 0)
2297- EmitDefault(expr.Type , il);
2308+ if (exprType != typeof(void) && (parent & ParentFlags.IgnoreResult) == 0)
2309+ EmitDefault(exprType , il);
22982310 return true;
22992311
23002312 case ExpressionType.Index:
@@ -3565,7 +3577,8 @@ public static bool TryEmitConstant(bool considerClosure, Type exprType, Type con
35653577 return true;
35663578 }
35673579
3568- private static bool TryEmitPrimitiveOrEnumOrDecimalConstant(ILGenerator il, object constValue, Type constType)
3580+ /// <summary>Emit the IL for the value of the primitive type.</summary>
3581+ public static bool TryEmitPrimitiveOrEnumOrDecimalConstant(ILGenerator il, object constValue, Type constType)
35693582 {
35703583 if (constType.IsEnum)
35713584 constType = Enum.GetUnderlyingType(constType);
@@ -6588,9 +6601,28 @@ public static bool IsCandidateForInterpretation(Expression expr)
65886601 expr is BinaryExpression;
65896602 }
65906603
6604+ /// <summary>Wraps `TryInterpretPrimitive` in the try catch block.
6605+ /// In case of exception FEC will emit the whole computation to throw exception in the invocation phase</summary>
6606+ public static bool TryInterpret(out object result, Expression expr)
6607+ {
6608+ Debug.Assert(expr.Type.IsPrimitive);
6609+ try
6610+ {
6611+ if (TryInterpretPrimitive(out result, expr))
6612+ return true;
6613+ }
6614+ catch
6615+ {
6616+ // eat up the expression this time
6617+ }
6618+ result = false;
6619+ return false;
6620+ }
6621+
65916622 /// <summary>In case of exception FEC will emit the whole computation to throw exception in the invocation phase</summary>
65926623 public static bool TryInterpretBoolean(out bool result, Expression expr)
65936624 {
6625+ Debug.Assert(expr.Type.IsPrimitive);
65946626 try
65956627 {
65966628 if (TryInterpretPrimitive(out var resultObj, expr))
@@ -6610,7 +6642,6 @@ public static bool TryInterpretBoolean(out bool result, Expression expr)
66106642 /// <summary>Tries to interpret the expression of the Primitive type of Constant, Convert, Logical, Comparison, Arithmetic.</summary>
66116643 public static bool TryInterpretPrimitive(out object result, Expression expr)
66126644 {
6613- Debug.Assert(expr.Type.IsPrimitive);
66146645 result = null;
66156646
66166647 // The order of the checks for the type of the expression is deliberate,
0 commit comments