Skip to content

Commit c1d64f4

Browse files
authored
Merge branch 'master' into fix-toexpr-lifttonull
2 parents 087f42f + 2b4127c commit c1d64f4

File tree

4 files changed

+71
-41
lines changed

4 files changed

+71
-41
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,7 @@ public static bool TryEmit(Expression expr, IReadOnlyList<PE> paramExprs,
18581858
case ExpressionType.Equal:
18591859
case ExpressionType.NotEqual:
18601860
var binaryExpr = (BinaryExpression)expr;
1861-
return TryEmitComparison(binaryExpr.Left, binaryExpr.Right, binaryExpr.NodeType, paramExprs, il, ref closure, setup, parent);
1861+
return TryEmitComparison(binaryExpr.Left, binaryExpr.Right, binaryExpr.NodeType, expr.Type, paramExprs, il, ref closure, setup, parent);
18621862

18631863
case ExpressionType.Add:
18641864
case ExpressionType.AddChecked:
@@ -2723,7 +2723,7 @@ private static bool TryEmitNot(UnaryExpression expr, IReadOnlyList<PE> paramExpr
27232723
if (expr.Operand.NodeType == ExpressionType.Equal)
27242724
{
27252725
var equalExpr = (BinaryExpression)expr.Operand;
2726-
return TryEmitComparison(equalExpr.Left, equalExpr.Right, ExpressionType.NotEqual, paramExprs, il, ref closure, setup, parent);
2726+
return TryEmitComparison(equalExpr.Left, equalExpr.Right, ExpressionType.NotEqual, equalExpr.Type, paramExprs, il, ref closure, setup, parent);
27272727
}
27282728

27292729
if (!TryEmit(expr.Operand, paramExprs, il, ref closure, setup, parent))
@@ -4391,7 +4391,7 @@ private static bool TryEmitSwitch(SwitchExpression expr, IReadOnlyList<PE> param
43914391

43924392
foreach (var caseTestValue in cs.TestValues)
43934393
{
4394-
if (!TryEmitComparison(expr.SwitchValue, caseTestValue, ExpressionType.Equal, paramExprs, il, ref closure, setup, dontIgnoreTestResult))
4394+
if (!TryEmitComparison(expr.SwitchValue, caseTestValue, ExpressionType.Equal, typeof(bool), paramExprs, il, ref closure, setup, dontIgnoreTestResult))
43954395
return false;
43964396
il.Emit(OpCodes.Brtrue, labels[caseIndex]);
43974397
}
@@ -4419,7 +4419,7 @@ private static bool TryEmitSwitch(SwitchExpression expr, IReadOnlyList<PE> param
44194419
return true;
44204420
}
44214421

4422-
private static bool TryEmitComparison(Expression exprLeft, Expression exprRight, ExpressionType expressionType,
4422+
private static bool TryEmitComparison(Expression exprLeft, Expression exprRight, ExpressionType expressionType, Type exprType,
44234423
#if LIGHT_EXPRESSION
44244424
IParameterProvider paramExprs,
44254425
#else
@@ -4579,10 +4579,19 @@ var methodName
45794579
EmitLoadLocalVariableAddress(il, lVarIndex);
45804580
EmitMethodCall(il, leftNullableHasValueGetterMethod);
45814581

4582+
var isLiftedToNull = exprType == typeof(bool?);
4583+
var leftHasValueVar = -1;
4584+
if (isLiftedToNull)
4585+
EmitStoreAndLoadLocalVariable(il, leftHasValueVar = il.GetNextLocalVarIndex(typeof(bool)));
4586+
45824587
// ReSharper disable once AssignNullToNotNullAttribute
45834588
EmitLoadLocalVariableAddress(il, rVarIndex);
45844589
EmitMethodCall(il, leftNullableHasValueGetterMethod);
45854590

4591+
var rightHasValueVar = -1;
4592+
if (isLiftedToNull)
4593+
EmitStoreAndLoadLocalVariable(il, rightHasValueVar = il.GetNextLocalVarIndex(typeof(bool)));
4594+
45864595
switch (expressionType)
45874596
{
45884597
case ExpressionType.Equal:
@@ -4610,6 +4619,20 @@ var methodName
46104619
default:
46114620
return false;
46124621
}
4622+
4623+
if (isLiftedToNull)
4624+
{
4625+
var resultLabel = il.DefineLabel();
4626+
var isNullLabel = il.DefineLabel();
4627+
EmitLoadLocalVariable(il, leftHasValueVar);
4628+
il.Emit(OpCodes.Brfalse, isNullLabel);
4629+
EmitLoadLocalVariable(il, rightHasValueVar);
4630+
il.Emit(OpCodes.Brtrue, resultLabel);
4631+
il.MarkLabel(isNullLabel);
4632+
il.Emit(OpCodes.Pop);
4633+
il.Emit(OpCodes.Ldnull);
4634+
il.MarkLabel(resultLabel);
4635+
}
46134636
}
46144637

46154638
return il.EmitPopIfIgnoreResult(parent);
@@ -6633,27 +6656,28 @@ void PrintPart(Expression part)
66336656

66346657
if (e is BinaryExpression b)
66356658
{
6636-
if (e.NodeType == ExpressionType.ArrayIndex)
6659+
var nodeType = e.NodeType;
6660+
if (nodeType == ExpressionType.ArrayIndex)
66376661
{
66386662
b.Left.ToCSharpString(sb.Append('('), lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant).Append(')');
66396663
return b.Right.ToCSharpString(sb.Append("["), lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant).Append("]");
66406664
}
66416665

6642-
if (e.NodeType == ExpressionType.Assign ||
6643-
e.NodeType == ExpressionType.PowerAssign ||
6644-
e.NodeType == ExpressionType.AndAssign ||
6645-
e.NodeType == ExpressionType.OrAssign ||
6646-
e.NodeType == ExpressionType.AddAssign ||
6647-
e.NodeType == ExpressionType.ExclusiveOrAssign ||
6648-
e.NodeType == ExpressionType.AddAssignChecked ||
6649-
e.NodeType == ExpressionType.SubtractAssign ||
6650-
e.NodeType == ExpressionType.SubtractAssignChecked ||
6651-
e.NodeType == ExpressionType.MultiplyAssign ||
6652-
e.NodeType == ExpressionType.MultiplyAssignChecked ||
6653-
e.NodeType == ExpressionType.DivideAssign ||
6654-
e.NodeType == ExpressionType.LeftShiftAssign ||
6655-
e.NodeType == ExpressionType.RightShiftAssign ||
6656-
e.NodeType == ExpressionType.ModuloAssign
6666+
if (nodeType == ExpressionType.Assign ||
6667+
nodeType == ExpressionType.PowerAssign ||
6668+
nodeType == ExpressionType.AndAssign ||
6669+
nodeType == ExpressionType.OrAssign ||
6670+
nodeType == ExpressionType.AddAssign ||
6671+
nodeType == ExpressionType.ExclusiveOrAssign ||
6672+
nodeType == ExpressionType.AddAssignChecked ||
6673+
nodeType == ExpressionType.SubtractAssign ||
6674+
nodeType == ExpressionType.SubtractAssignChecked ||
6675+
nodeType == ExpressionType.MultiplyAssign ||
6676+
nodeType == ExpressionType.MultiplyAssignChecked ||
6677+
nodeType == ExpressionType.DivideAssign ||
6678+
nodeType == ExpressionType.LeftShiftAssign ||
6679+
nodeType == ExpressionType.RightShiftAssign ||
6680+
nodeType == ExpressionType.ModuloAssign
66576681
)
66586682
{
66596683
// todo: @perf handle the right part is condition with the blocks for If and/or Else, e.g. see #261 test `Serialize_the_nullable_struct_array`
@@ -6667,39 +6691,37 @@ void PrintPart(Expression part)
66676691
}
66686692

66696693
b.Left.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant);
6670-
if (e.NodeType == ExpressionType.PowerAssign)
6694+
if (nodeType == ExpressionType.PowerAssign)
66716695
{
66726696
sb.Append(" = System.Math.Pow(");
66736697
b.Left.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant).Append(", ");
66746698
return b.Right.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant).Append(")");
66756699
}
66766700

6677-
sb.Append(OperatorToCSharpString(e.NodeType));
6701+
sb.Append(OperatorToCSharpString(nodeType));
66786702

66796703
return b.Right.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant);
66806704
}
66816705

6682-
6683-
b.Left.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant);
6706+
b.Left.ToCSharpString(sb.Append('('), lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant);
66846707

6685-
if (e.NodeType == ExpressionType.Equal)
6708+
if (nodeType == ExpressionType.Equal)
66866709
{
66876710
if (b.Right is ConstantExpression r && r.Value is bool rb && rb)
66886711
return sb;
66896712
sb.Append(" == ");
66906713
}
6691-
else if (e.NodeType == ExpressionType.NotEqual)
6714+
else if (nodeType == ExpressionType.NotEqual)
66926715
{
66936716
if (b.Right is ConstantExpression r && r.Value is bool rb)
66946717
return rb ? sb.Append(" == false") : sb;
66956718
sb.Append(" != ");
66966719
}
66976720
else
6698-
{
6699-
sb.Append(OperatorToCSharpString(e.NodeType));
6700-
}
6721+
sb.Append(OperatorToCSharpString(nodeType));
67016722

6702-
return b.Right.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant);
6723+
return b.Right.ToCSharpString(sb, lineIdent, stripNamespace, printType, identSpaces, tryPrintConstant)
6724+
.Append(')');
67036725
}
67046726

67056727
return sb.Append(e.ToString()); // falling back ToString and hoping for the best
@@ -7070,23 +7092,23 @@ public static string ToCode(this Type type,
70707092
string buildInTypeString = null;
70717093
if (type == typeof(void))
70727094
buildInTypeString = "void";
7073-
if (type == typeof(object))
7095+
else if (type == typeof(object))
70747096
buildInTypeString = "object";
7075-
if (type == typeof(bool))
7097+
else if (type == typeof(bool))
70767098
buildInTypeString = "bool";
7077-
if (type == typeof(int))
7099+
else if (type == typeof(int))
70787100
buildInTypeString = "int";
7079-
if (type == typeof(short))
7101+
else if (type == typeof(short))
70807102
buildInTypeString = "short";
7081-
if (type == typeof(byte))
7103+
else if (type == typeof(byte))
70827104
buildInTypeString = "byte";
7083-
if (type == typeof(double))
7105+
else if (type == typeof(double))
70847106
buildInTypeString = "double";
7085-
if (type == typeof(float))
7107+
else if (type == typeof(float))
70867108
buildInTypeString = "float";
7087-
if (type == typeof(char))
7109+
else if (type == typeof(char))
70887110
buildInTypeString = "char";
7089-
if (type == typeof(string))
7111+
else if (type == typeof(string))
70907112
buildInTypeString = "string";
70917113

70927114
if (buildInTypeString != null)

test/FastExpressionCompiler.IssueTests/Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public int Run()
1818
return 1;
1919
}
2020

21-
// [Test]
21+
[Test]
2222
public void Test1()
2323
{
2424
var expr = Lambda<Func<object>>(

test/FastExpressionCompiler.TestsRunner.Net472/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ void Run(Func<int> run, string name = null)
201201
Run(new Issue308_Wrong_delegate_type_returned_with_closure().Run);
202202
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue308_Wrong_delegate_type_returned_with_closure().Run);
203203

204+
Run(new Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run);
205+
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run);
206+
204207
Run(new Issue310_InvalidProgramException_ignored_nullable().Run);
205208
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue310_InvalidProgramException_ignored_nullable().Run);
206209

test/FastExpressionCompiler.TestsRunner/Program.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ public class Program
99
{
1010
public static void Main()
1111
{
12-
RunAllTests();
12+
// RunAllTests();
1313

14+
// new Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run();
15+
new FastExpressionCompiler.LightExpression.IssueTests.Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run();
1416
// new FastExpressionCompiler.LightExpression.IssueTests.Issue308_Wrong_delegate_type_returned_with_closure().Run();
1517

1618
// new FastExpressionCompiler.LightExpression.IssueTests.Issue307_Switch_with_fall_through_throws_InvalidProgramException().Run();
@@ -226,6 +228,9 @@ void Run(Func<int> run, string name = null)
226228
Run(new Issue308_Wrong_delegate_type_returned_with_closure().Run);
227229
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue308_Wrong_delegate_type_returned_with_closure().Run);
228230

231+
Run(new Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run);
232+
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue309_InvalidProgramException_with_MakeBinary_liftToNull_true().Run);
233+
229234
Run(new Issue310_InvalidProgramException_ignored_nullable().Run);
230235
Run(new FastExpressionCompiler.LightExpression.IssueTests.Issue310_InvalidProgramException_ignored_nullable().Run);
231236

0 commit comments

Comments
 (0)