Skip to content

Commit 159eccb

Browse files
author
maximv
committed
fixing block without variables is pushed into the stack; wip failed test in ArithmeticOperationsTests
1 parent 4490de2 commit 159eccb

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ public ClosureInfo(ClosureStatus status, object[] constValues = null, int[] cons
570570
constValues == null ? Tools.Empty<int>() : constUsage ?? new int[constValues.Length]);
571571

572572
NonPassedParameters = Tools.Empty<ParameterExpression>();
573-
NestedLambdas = Tools.Empty<NestedLambdaInfo>();
573+
NestedLambdas = Tools.Empty<NestedLambdaInfo>();
574574

575575
LastEmitIsAddress = false;
576576
CurrentTryCatchFinallyIndex = -1;
@@ -1317,13 +1317,15 @@ private static bool TryCollectBoundConstants(ref ClosureInfo closure, Expression
13171317
{
13181318
if (blockVarExprs.Count == 1)
13191319
closure.PushBlockWithVars(blockVarExprs[0]);
1320-
else
1320+
else if (blockVarExprs.Count != 0)
13211321
closure.PushBlockWithVars(blockVarExprs);
13221322

13231323
for (var i = 0; i < blockExprCount; i++)
13241324
if (!TryCollectBoundConstants(ref closure, blockExprs[i], paramExprs, isNestedLambda, ref rootClosure, flags))
13251325
return false;
1326-
closure.PopBlock();
1326+
1327+
if (blockVarExprs.Count != 0)
1328+
closure.PopBlock();
13271329
}
13281330

13291331
return true;
@@ -1823,8 +1825,7 @@ public static bool TryEmit(Expression expr, IReadOnlyList<PE> paramExprs,
18231825
case ExpressionType.ExclusiveOr:
18241826
case ExpressionType.LeftShift:
18251827
case ExpressionType.RightShift:
1826-
var arithmeticExpr = (BinaryExpression)expr;
1827-
return TryEmitArithmetic(arithmeticExpr, expr.NodeType, paramExprs, il, ref closure, setup, parent);
1828+
return TryEmitArithmetic((BinaryExpression)expr, expr.NodeType, paramExprs, il, ref closure, setup, parent);
18281829

18291830
case ExpressionType.AndAlso:
18301831
case ExpressionType.OrElse:
@@ -4469,10 +4470,9 @@ private static bool TryEmitArithmetic(BinaryExpression expr, ExpressionType expr
44694470
EmitStoreLocalVariableAndLoadItsAddress(il, lefType);
44704471

44714472
il.Emit(OpCodes.Dup);
4472-
il.Emit(OpCodes.Call, lefType.FindNullableHasValueGetterMethod());
4473-
4473+
il.Emit(OpCodes.Call, lefType.FindNullableHasValueGetterMethod());
44744474
il.Emit(OpCodes.Brfalse, leftNoValueLabel);
4475-
il.Emit(OpCodes.Call, lefType.FindNullableGetValueOrDefaultMethod());
4475+
il.Emit(OpCodes.Call, lefType.FindNullableGetValueOrDefaultMethod());
44764476
}
44774477
else if (!TryEmit(leftExpr, paramExprs, il, ref closure, setup, flags))
44784478
return false;
@@ -4491,9 +4491,9 @@ private static bool TryEmitArithmetic(BinaryExpression expr, ExpressionType expr
44914491
EmitStoreLocalVariableAndLoadItsAddress(il, rightType);
44924492

44934493
il.Emit(OpCodes.Dup);
4494-
il.Emit(OpCodes.Call, rightType.FindNullableHasValueGetterMethod());
4494+
il.Emit(OpCodes.Call, rightType.FindNullableHasValueGetterMethod());
44954495
il.Emit(OpCodes.Brfalse, rightNoValueLabel);
4496-
il.Emit(OpCodes.Call, rightType.FindNullableGetValueOrDefaultMethod());
4496+
il.Emit(OpCodes.Call, rightType.FindNullableGetValueOrDefaultMethod());
44974497
}
44984498
else if (!TryEmit(rightExpr, paramExprs, il, ref closure, setup, flags))
44994499
return false;
@@ -4518,8 +4518,7 @@ private static bool TryEmitArithmetic(BinaryExpression expr, ExpressionType expr
45184518
if (exprType.IsNullable())
45194519
{
45204520
var endL = il.DefineLabel();
4521-
var locIndex = InitValueTypeVariable(il, exprType);
4522-
EmitLoadLocalVariable(il, locIndex);
4521+
EmitLoadLocalVariable(il, InitValueTypeVariable(il, exprType));
45234522
il.Emit(OpCodes.Br_S, endL);
45244523
il.MarkLabel(valueLabel);
45254524
il.Emit(OpCodes.Newobj, exprType.GetTypeInfo().DeclaredConstructors.GetFirst());
@@ -4566,14 +4565,14 @@ private static bool TryEmitArithmeticOperation(BinaryExpression expr, Expression
45664565
else
45674566
{
45684567
var methodName
4569-
= exprNodeType == ExpressionType.Add ? "op_Addition"
4570-
: exprNodeType == ExpressionType.AddChecked ? "op_Addition"
4571-
: exprNodeType == ExpressionType.Subtract ? "op_Subtraction"
4568+
= exprNodeType == ExpressionType.Add ? "op_Addition"
4569+
: exprNodeType == ExpressionType.AddChecked ? "op_Addition"
4570+
: exprNodeType == ExpressionType.Subtract ? "op_Subtraction"
45724571
: exprNodeType == ExpressionType.SubtractChecked ? "op_Subtraction"
4573-
: exprNodeType == ExpressionType.Multiply ? "op_Multiply"
4572+
: exprNodeType == ExpressionType.Multiply ? "op_Multiply"
45744573
: exprNodeType == ExpressionType.MultiplyChecked ? "op_Multiply"
4575-
: exprNodeType == ExpressionType.Divide ? "op_Division"
4576-
: exprNodeType == ExpressionType.Modulo ? "op_Modulus"
4574+
: exprNodeType == ExpressionType.Divide ? "op_Division"
4575+
: exprNodeType == ExpressionType.Modulo ? "op_Modulus"
45774576
: null;
45784577

45794578
if (methodName != null)
@@ -4590,7 +4589,6 @@ var methodName
45904589

45914590
if (method == null)
45924591
return false;
4593-
45944592
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
45954593
return true;
45964594
}
@@ -5016,7 +5014,6 @@ internal static MethodInfo FindMethod(this Type type, string methodName)
50165014
for (var i = 0; i < methods.Length; i++)
50175015
if (methods[i].Name == methodName)
50185016
return methods[i];
5019-
50205017
return type.BaseType?.FindMethod(methodName);
50215018
}
50225019

test/FastExpressionCompiler.IssueTests/Issue67_Equality_comparison_with_nullables_throws_at_delegate_invoke.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,26 +122,24 @@ public void Comparing_nullable_unequal_works()
122122
var int32Comparand = 1;
123123
Expression<Func<Foo, bool>> e = foo => foo.Prop != int32Comparand;
124124

125-
var f = e.CompileFast(true);
126125
var f2 = e.Compile();
127-
Assert.IsNotNull(f);
126+
var f = e.CompileFast(true);
128127

129-
Assert.AreEqual(f2(new Foo() { Prop = 1 }), f(new Foo() { Prop = 1 }));
130-
Assert.AreEqual(f2(new Foo() { Prop = null }), f(new Foo() { Prop = null }));
131-
Assert.AreEqual(f2(new Foo() { Prop = -1 }), f(new Foo() { Prop = -1 }));
132-
Assert.AreEqual(f2(new Foo() { Prop = 0 }), f(new Foo() { Prop = 0 }));
128+
Assert.AreEqual(f2(new Foo() { Prop = 1 }), f(new Foo() { Prop = 1 }));
129+
Assert.AreEqual(f2(new Foo() { Prop = null }), f(new Foo() { Prop = null }));
130+
Assert.AreEqual(f2(new Foo() { Prop = -1 }), f(new Foo() { Prop = -1 }));
131+
Assert.AreEqual(f2(new Foo() { Prop = 0 }), f(new Foo() { Prop = 0 }));
133132

134133
int? int32Comparand2 = null;
135134
Expression<Func<Foo, bool>> e2 = foo => foo.Prop != int32Comparand;
136135

137-
var fa = e2.CompileFast(true);
138136
var fa2 = e2.Compile();
139-
Assert.IsNotNull(fa);
137+
var fa = e2.CompileFast(true);
140138

141-
Assert.AreEqual(fa2(new Foo() { Prop = 1 }), fa(new Foo() { Prop = 1 }));
139+
Assert.AreEqual(fa2(new Foo() { Prop = 1 }), fa(new Foo() { Prop = 1 }));
142140
Assert.AreEqual(fa2(new Foo() { Prop = null }), fa(new Foo() { Prop = null }));
143-
Assert.AreEqual(fa2(new Foo() { Prop = -1 }), fa(new Foo() { Prop = -1 }));
144-
Assert.AreEqual(fa2(new Foo() { Prop = 0 }), fa(new Foo() { Prop = 0 }));
141+
Assert.AreEqual(fa2(new Foo() { Prop = -1 }), fa(new Foo() { Prop = -1 }));
142+
Assert.AreEqual(fa2(new Foo() { Prop = 0 }), fa(new Foo() { Prop = 0 }));
145143
}
146144

147145
[Test]

test/FastExpressionCompiler.UnitTests/ArithmeticOperationsTests.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public int Run()
2424
Can_substract_with_unchecked_overflow();
2525
Can_not_substract_with_checked_overflow();
2626
Can_modulus_custom();
27+
// Can_modulus_custom_in_Action();
2728
Can_modulus();
2829
Can_bit_or_1();
2930
Can_bit_and_1();
@@ -48,9 +49,9 @@ public int Run()
4849
Can_add_strings();
4950
Can_add_string_and_not_string();
5051

51-
return 28;
52+
return 29;
5253
#else
53-
return 25;
54+
return 26;
5455
#endif
5556
}
5657

@@ -182,11 +183,24 @@ public void Can_modulus_custom()
182183
var expr = Lambda<Func<BigInteger, BigInteger, BigInteger>>(Modulo(a, b), a, b);
183184

184185
var f = expr.CompileFast(true);
185-
186-
Assert.IsNotNull(f);
187186
Assert.AreEqual(new BigInteger(1), f(7, 6));
188187
}
189188

189+
[Test, Ignore("todo: fixme")]
190+
public void Can_modulus_custom_in_Action()
191+
{
192+
var a = Parameter(typeof(BigInteger), "a");
193+
var b = Parameter(typeof(BigInteger), "b");
194+
var expr = Lambda<Action<BigInteger, BigInteger>>(Modulo(a, b), a, b);
195+
196+
var fs = expr.CompileSys();
197+
fs.PrintIL();
198+
199+
var fx = expr.CompileFast(true);
200+
fx.PrintIL();
201+
fx(7, 6);
202+
}
203+
190204
[Test]
191205
public void Can_modulus()
192206
{

0 commit comments

Comments
 (0)