Skip to content

Commit cbda7ad

Browse files
committed
support for the Arithmetic interpreter #468
1 parent c156103 commit cbda7ad

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)