Skip to content

Commit

Permalink
compiler/parser: make 'used as value' error message the same of gc
Browse files Browse the repository at this point in the history
For #385
  • Loading branch information
gazerro committed Jun 26, 2021
1 parent 7e4919e commit f85cac8
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 35 deletions.
38 changes: 26 additions & 12 deletions compiler/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package compiler
import (
"errors"
"fmt"
"strings"
"unicode"
"unicode/utf8"

Expand Down Expand Up @@ -589,10 +590,7 @@ LABEL:
if cond != nil {
condition, _ = cond.(ast.Expression)
if condition == nil {
if a, ok := cond.(*ast.Assignment); ok && a.Type == ast.AssignmentSimple {
panic(syntaxError(tok.pos, "assignment %s used as value", init))
}
panic(syntaxError(tok.pos, "%s used as value", init))
panic(cannotUseAsValueError(pos, init))
}
}
var post ast.Node
Expand All @@ -611,10 +609,7 @@ LABEL:
if init != nil {
condition, _ = init.(ast.Expression)
if condition == nil {
if a, ok := init.(*ast.Assignment); ok && a.Type == ast.AssignmentSimple {
panic(syntaxError(tok.pos, "assignment %s used as value", init))
}
panic(syntaxError(tok.pos, "%s used as value", init))
panic(cannotUseAsValueError(pos, init))
}
}
pos.End = tok.pos.End
Expand Down Expand Up @@ -892,10 +887,7 @@ LABEL:
} else if init != nil {
expr, _ = init.(ast.Expression)
if expr == nil {
if a, ok := init.(*ast.Assignment); ok && a.Type == ast.AssignmentSimple {
panic(syntaxError(tok.pos, "assignment %s used as value", init))
}
panic(syntaxError(tok.pos, "%s used as value", init))
panic(cannotUseAsValueError(pos, init))
}
init = nil
}
Expand Down Expand Up @@ -1696,6 +1688,28 @@ func (p *parsing) parseAssignment(variables []ast.Expression, tok token, canBeRa
return node, tok
}

// cannotUseAsValueError returns a syntax error returned when node is used as
// value at position pos.
func cannotUseAsValueError(pos *ast.Position, node ast.Node) *SyntaxError {
if a, ok := node.(*ast.Assignment); ok && a.Type == ast.AssignmentSimple {
return syntaxError(pos, "cannot use assignment (%s) = (%s) as value",
printExpressions(a.Lhs), printExpressions(a.Rhs))
}
panic(syntaxError(pos, "cannot use %s as value", node))
}

// printExpressions prints expressions as a comma separated list.
func printExpressions(expressions []ast.Expression) string {
var b strings.Builder
for i, e := range expressions {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(e.String())
}
return b.String()
}

// addNode adds a node to the tree. It adds the node as a child to the current
// parent node and sets the node as new ancestor if necessary.
func (p *parsing) addNode(node ast.Node) {
Expand Down
20 changes: 4 additions & 16 deletions compiler/parser_switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,8 @@ func (p *parsing) parseSwitch(tok token, end tokenTyp) ast.Node {
// TODO (Gianluca): should error contain the position of the
// expression which caused the error instead of the token (as Go
// does)?
if !ok {
panic(syntaxError(tok.pos, "assignment %s used as value", assignment))
}
if ta.Type != nil {
panic(syntaxError(tok.pos, "%s used as value", assignment))
}
if len(assignment.Lhs) != 1 {
panic(syntaxError(tok.pos, "%s used as value", assignment))
if !ok || ta.Type != nil || len(assignment.Lhs) != 1 {
panic(cannotUseAsValueError(tok.pos, assignment))
}
afterSemicolon = assignment
} else {
Expand All @@ -160,15 +154,9 @@ func (p *parsing) parseSwitch(tok token, end tokenTyp) ast.Node {
if len(assignment.Rhs) != 1 {
panic(syntaxError(tok.pos, "unexpected %s, expecting expression", want))
}
if len(assignment.Lhs) != 1 {
panic(syntaxError(tok.pos, "%s used as value", assignment))
}
ta, ok := assignment.Rhs[0].(*ast.TypeAssertion)
if !ok {
panic(syntaxError(tok.pos, "assignment %s used as value", assignment))
}
if ta.Type != nil {
panic(syntaxError(tok.pos, "%s used as value", assignment))
if !ok || ta.Type != nil || len(assignment.Lhs) != 1 {
panic(cannotUseAsValueError(tok.pos, assignment))
}
afterSemicolon = assignment
}
Expand Down
2 changes: 2 additions & 0 deletions test/compare/testdata/misc/switch2.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func main() {
switch 5 { case 'a': }
switch 'a' { case 5: }
switch 5.4 { case 2i: } // ERROR `constant 2i truncated to real`
switch a = 1 { case true: } // ERROR `cannot use assignment (a) = (1) as value`
switch a := 1 { case true: } // ERROR `cannot use a := 1 as value`
switch 1 < 2 { case true: }
switch a < "b" { case true: }
switch a { case "b": }
Expand Down
3 changes: 2 additions & 1 deletion test/compare/testdata/syntax/for_statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ func main() {
for ; {} // ERROR `syntax error: unexpected {, expecting for loop condition`
for ; true {} // ERROR `syntax error: unexpected {, expecting semicolon or newline`
for ; ; { break }
for a := 5 {} // ERROR `syntax error: a := 5 used as value`
for a = 5 {} // ERROR `syntax error: cannot use assignment (a) = (5) as value`
for a := 5 {} // ERROR `syntax error: cannot use a := 5 as value`
for a := 5; {} // ERROR `syntax error: unexpected {, expecting for loop condition`
for a := 5; true {} // ERROR `syntax error: unexpected {, expecting semicolon or newline`
for a := false; a; {}
Expand Down
13 changes: 7 additions & 6 deletions test/compare/testdata/syntax/if_statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ func main() {
if f() {}
if <-ch {} // ERROR `non-bool <-ch (type int) used as if condition`
if <-chb {}
if ch <- 3 {} // ERROR `ch <- 3 used as value`
if i++ for {} // ERROR `syntax error: i++ used as value`
if i++ {} // ERROR `syntax error: i++ used as value`
if i-- {} // ERROR `syntax error: i-- used as value`
if i = 3 {} // ERROR `syntax error: assignment i = 3 used as value`
if i := 3 { _ = i } // ERROR `syntax error: i := 3 used as value`
if ch <- 3 {} // ERROR `cannot use ch <- 3 as value`
if i++ for {} // ERROR `syntax error: cannot use i++ as value`
if i++ {} // ERROR `syntax error: cannot use i++ as value`
if i-- {} // ERROR `syntax error: cannot use i-- as value`
if i = 3 {} // ERROR `syntax error: cannot use assignment (i) = (3) as value`
if a, b = 3, 6 {} // ERROR `syntax error: cannot use assignment (a, b) = (3, 6) as value`
if i := 3 { _ = i } // ERROR `syntax error: cannot use i := 3 as value`
if print(); {} // ERROR `syntax error: missing condition in if statement`
if <-ch; {} // ERROR `syntax error: missing condition in if statement`
if ch <- 3; {} // ERROR `syntax error: missing condition in if statement`
Expand Down

0 comments on commit f85cac8

Please sign in to comment.