checker: fix checker enum infix error

pull/4326/head
Daniel Däschle 2020-04-10 14:44:01 +02:00 committed by GitHub
parent adb379dd63
commit 42b3b19af4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 21 deletions

View File

@ -502,7 +502,8 @@ mut:
pub struct EnumField { pub struct EnumField {
name string name string
pos token.Position pos token.Position
exprs []Expr expr Expr
has_expr bool
} }
pub struct EnumDecl { pub struct EnumDecl {

View File

@ -562,12 +562,12 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) { pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) {
for field in decl.fields { for field in decl.fields {
for expr in field.exprs { if field.has_expr {
match expr { match field.expr {
ast.IntegerLiteral {} ast.IntegerLiteral {}
ast.PrefixExpr {} ast.PrefixExpr {}
else { else {
mut pos := expr_pos(expr) pos := expr_pos(field.expr)
if pos.pos == 0 { if pos.pos == 0 {
pos = field.pos pos = field.pos
} }
@ -1064,7 +1064,18 @@ fn expr_pos(node ast.Expr) token.Position {
ast.IfExpr { return it.pos } ast.IfExpr { return it.pos }
// ast.IfGuardExpr { } // ast.IfGuardExpr { }
ast.IndexExpr { return it.pos } ast.IndexExpr { return it.pos }
ast.InfixExpr { return it.pos } ast.InfixExpr {
left_pos := expr_pos(it.left)
right_pos := expr_pos(it.right)
if left_pos.pos == 0 || right_pos.pos == 0 {
return it.pos
}
return token.Position{
line_nr: it.pos.line_nr
pos: left_pos.pos
len: right_pos.pos - left_pos.pos + right_pos.len
}
}
ast.IntegerLiteral { return it.pos } ast.IntegerLiteral { return it.pos }
ast.MapInit { return it.pos } ast.MapInit { return it.pos }
ast.MatchExpr { return it.pos } ast.MatchExpr { return it.pos }

View File

@ -2,5 +2,12 @@ vlib/v/checker/tests/inout/enum_err.v:2:13: error: default value for enum has to
1| enum Color { 1| enum Color {
2| green = 'green', 2| green = 'green',
~~~~~~~ ~~~~~~~
3| blue, 3| yellow = 1+1,
4| } 4| blue,
vlib/v/checker/tests/inout/enum_err.v:3:14: error: default value for enum has to be an integer
1| enum Color {
2| green = 'green',
3| yellow = 1+1,
~~~
4| blue,
5| }

View File

@ -1,4 +1,5 @@
enum Color { enum Color {
green = 'green', green = 'green',
yellow = 1+1,
blue, blue,
} }

View File

@ -210,11 +210,9 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
f.writeln('enum $name {') f.writeln('enum $name {')
for field in it.fields { for field in it.fields {
f.write('\t$field.name') f.write('\t$field.name')
if field.exprs.len > 0 { if field.has_expr {
f.write(' = ') f.write(' = ')
for expr in field.exprs { f.expr(field.expr)
f.expr(expr)
}
f.writeln(',') f.writeln(',')
} else { } else {
f.writeln('') f.writeln('')

View File

@ -367,12 +367,10 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.typedefs.writeln('typedef enum {') g.typedefs.writeln('typedef enum {')
for field in it.fields { for field in it.fields {
g.typedefs.write('\t${enum_name}_$field.name') g.typedefs.write('\t${enum_name}_$field.name')
if field.exprs.len > 0 { if field.has_expr {
g.typedefs.write(' = ') g.typedefs.write(' = ')
}
for expr in field.exprs {
pos := g.out.len pos := g.out.len
g.expr(expr) g.expr(field.expr)
expr_str := g.out.after(pos) expr_str := g.out.after(pos)
g.out.go_back(expr_str.len) g.out.go_back(expr_str.len)
g.typedefs.write('$expr_str') g.typedefs.write('$expr_str')

View File

@ -843,13 +843,14 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
// will fudge left shift as it makes it right assoc // will fudge left shift as it makes it right assoc
// `arr << 'a'` | `arr << 'a' + 'b'` // `arr << 'a'` | `arr << 'a' + 'b'`
tok := p.tok tok := p.tok
pos := tok.position()
p.next() p.next()
right := p.expr(precedence - 1) right := p.expr(precedence - 1)
node = ast.InfixExpr{ node = ast.InfixExpr{
left: node left: node
right: right right: right
op: tok.kind op: tok.kind
pos: tok.position() pos:pos
} }
} else if p.tok.kind.is_infix() { } else if p.tok.kind.is_infix() {
node = p.infix_expr(node) node = p.infix_expr(node)
@ -1876,13 +1877,15 @@ fn (p mut Parser) enum_decl() ast.EnumDecl {
pos := p.tok.position() pos := p.tok.position()
val := p.check_name() val := p.check_name()
vals << val vals << val
mut exprs := []ast.Expr mut expr := ast.Expr{}
mut has_expr := false
// p.warn('enum val $val') // p.warn('enum val $val')
if p.tok.kind == .assign { if p.tok.kind == .assign {
p.next() p.next()
exprs << p.expr(0) expr = p.expr(0)
has_expr = true
} }
fields << ast.EnumField{val, pos, exprs} fields << ast.EnumField{val, pos, expr, has_expr}
// Allow commas after enum, helpful for // Allow commas after enum, helpful for
// enum Color { // enum Color {
// r,g,b // r,g,b