diff --git a/src/FastExpressionCompiler/FastExpressionCompiler.cs b/src/FastExpressionCompiler/FastExpressionCompiler.cs index ad8af976..e5a9a4ca 100644 --- a/src/FastExpressionCompiler/FastExpressionCompiler.cs +++ b/src/FastExpressionCompiler/FastExpressionCompiler.cs @@ -6978,7 +6978,6 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb var x = (ConditionalExpression)e; if (e.Type == typeof(void)) // otherwise output as ternary expression { - sb.NewLine(lineIdent, identSpaces); sb.Append("if ("); x.Test.ToCSharpString(sb, EnclosedIn.IfTest, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode); sb.Append(')'); @@ -7016,9 +7015,15 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb return BlockToCSharpString((BlockExpression)e, sb, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode); else { - sb.Append('{'); + var isExpressionBlock = e.Type != typeof(void) && sb.Length > 0; + sb.Append("{"); + if (isExpressionBlock) + sb.Append(" /* BlockExpression cannot be written in C#. Please rewrite the code inside these braces as a C# expression, or reorganize the parent expression as a block. */"); BlockToCSharpString((BlockExpression)e, sb, lineIdent + identSpaces, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode); - return sb.AddSemicolonIfFits().NewLineIdent(lineIdent).Append('}'); + + if (isExpressionBlock) + sb.Append("/* <- block result */"); + return sb.NewLineIdent(lineIdent).Append('}'); } } case ExpressionType.Loop: @@ -7170,12 +7175,11 @@ void PrintPart(Expression part) } case ExpressionType.Default: { - return e.Type == typeof(void) ? sb : // `default(void)` does not make sense in the C# - !e.Type.IsValueType && !e.Type.IsGenericParameter ? sb.Append("null") : - sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')'); + return e.Type == typeof(void) ? sb // `default(void)` does not make sense in the C# + : sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')'); } case ExpressionType.TypeIs: - case ExpressionType.TypeEqual: // TODO: type equal + case ExpressionType.TypeEqual: { var x = (TypeBinaryExpression)e; sb.Append('('); @@ -8127,4 +8131,3 @@ public RequiresUnreferencedCodeAttribute(string message) } } #endif -} diff --git a/test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs b/test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs index a3c88c70..16679727 100644 --- a/test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs +++ b/test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs @@ -32,15 +32,62 @@ public void Outputs_closed_generic_type_constant_correctly() } [Test] - public void Outputs_default_reference_type_is_just_null() + public void Lambda_with_block_body() { - var cs = Default(typeof(string)).ToCSharpString(); - Assert.AreEqual("null;", cs); + var variable = Parameter(typeof(int), "variable"); + var e = Lambda>(Block(new [] { variable }, Assign(variable, Constant(1)), Add(variable, Constant(2)))); + + var cs = e.ToCSharpString(); - cs = Default(typeof(System.Collections.Generic.List)).ToCSharpString(); - Assert.AreEqual("null;", cs); + Assert.AreEqual(""" + (Func)(() => + { + int variable = default; + variable = 1; + return (variable + 2); + }); + """, cs); } + [Test] + public void Nested_blocks() + { + var v1 = Parameter(typeof(int), "v1"); + var v2 = Parameter(typeof(int), "v2"); + var cs = Block(new [] { v1 }, + Assign(v1, Constant(2)), + Block(new [] { v2 }, + Assign(v2, Constant(3)), + AddAssign(v1, v2), + IfThen( + Equal(v1, Constant(5)), + Block( + Assign(v2, Constant(7)), + AddAssign(v1, v2) + ) + ) + ), + v1 + ).ToCSharpString(); + Console.WriteLine(cs); + Assert.AreEqual(""" + { + int v1 = default; + v1 = 2; + int v2 = default; + v2 = 3; + v1 += v2; + if (v1 == 5) + { + v2 = 7; + v1 += v2; + } + v1; + }; + """, cs); + } + + [Test] public void Somehow_handles_block_in_expression() { @@ -51,10 +98,10 @@ public void Somehow_handles_block_in_expression() variable )).ToCSharpString(); Assert.AreEqual(""" - (1 + { - int variable; + (1 + { /* BlockExpression cannot be written in C#. Please rewrite the code inside these braces as a C# expression, or reorganize the parent expression as a block. */ + int variable = default; variable = 2; - variable; + variable;/* <- block result */ }); """, cs); }