Skip to content

Commit

Permalink
ToCSharpCode: add comments to invalid block expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
exyi committed Oct 1, 2023
1 parent 3369c2b commit f0ca1d8
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 18 deletions.
21 changes: 12 additions & 9 deletions src/FastExpressionCompiler/FastExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6760,7 +6760,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
{
var x = (ConstantExpression)e;
if (x.Value == null)
return x.Type != null && x.Type.IsValueType
return x.Type != null
? sb.Append("default(").Append(x.Type.ToCode(stripNamespace, printType)).Append(')')
: sb.Append("null");

Expand Down Expand Up @@ -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(')');
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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('(');
Expand Down Expand Up @@ -8127,4 +8131,3 @@ public RequiresUnreferencedCodeAttribute(string message)
}
}
#endif
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net7.0</TargetFrameworks>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
63 changes: 55 additions & 8 deletions test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Func<int>>(Block(new [] { variable }, Assign(variable, Constant(1)), Add(variable, Constant(2))));

var cs = e.ToCSharpString();

cs = Default(typeof(System.Collections.Generic.List<string>)).ToCSharpString();
Assert.AreEqual("null;", cs);
Assert.AreEqual("""
(Func<int>)(() =>
{
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()
{
Expand All @@ -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);
}
Expand Down

0 comments on commit f0ca1d8

Please sign in to comment.