What's wrong
To match gofmt, GoGenerator.WriteCondition (Coder/Languages/GoGenerator.cs ~1597-1605) drops the outer parentheses of a BinaryExpression/UnaryExpression used as an if/for/switch clause. Go's grammar, however, has a composite-literal ambiguity: inside an if/for/switch header, TypeName{ is parsed as the start of the block. A composite literal that appears directly as an operand there must be parenthesised (Go spec: Composite literals, "parsing ambiguity"). The generator writes the struct construction bare.
Repro (reproduced with MSTest, output checked with go run)
AST: ReturnStatement(ConditionalExpression(BinaryExpression(VariableReference("p"), Equal, ConstructionExpression(Point){1, 2}), 1, 0)), with Point a two-field struct.
- Generated:
if p == Point{1, 2} {
go run: syntax error: unexpected }, expected := or = or comma
- Expected:
if p == (Point{1, 2}) {. Checked: this compiles and returns 1.
The same happens for an IfStatement/WhileStatement condition, and for the func() T { if … }() form that conditionals take in assignment/argument position, since all of them go through WriteCondition.
Suggested fix
In WriteCondition, when either direct operand (or a call receiver at the top level of the condition) is a ConstructionExpression that Go spells with braces (a struct literal: more than one argument or any MemberInitialiser), parenthesise that operand. Alternatively, keep the outer parentheses whenever the condition contains such an operand. Add a Go compile test for a struct-equality condition.
What's wrong
To match gofmt,
GoGenerator.WriteCondition(Coder/Languages/GoGenerator.cs~1597-1605) drops the outer parentheses of aBinaryExpression/UnaryExpressionused as anif/for/switchclause. Go's grammar, however, has a composite-literal ambiguity: inside anif/for/switchheader,TypeName{is parsed as the start of the block. A composite literal that appears directly as an operand there must be parenthesised (Go spec: Composite literals, "parsing ambiguity"). The generator writes the struct construction bare.Repro (reproduced with MSTest, output checked with
go run)AST:
ReturnStatement(ConditionalExpression(BinaryExpression(VariableReference("p"), Equal, ConstructionExpression(Point){1, 2}), 1, 0)), withPointa two-field struct.if p == Point{1, 2} {go run:syntax error: unexpected }, expected := or = or commaif p == (Point{1, 2}) {. Checked: this compiles and returns 1.The same happens for an
IfStatement/WhileStatementcondition, and for thefunc() T { if … }()form that conditionals take in assignment/argument position, since all of them go throughWriteCondition.Suggested fix
In
WriteCondition, when either direct operand (or a call receiver at the top level of the condition) is aConstructionExpressionthat Go spells with braces (a struct literal: more than one argument or anyMemberInitialiser), parenthesise that operand. Alternatively, keep the outer parentheses whenever the condition contains such an operand. Add a Go compile test for a struct-equality condition.