From 320fad49c5db9d65eb7ea6311858da34c7e5302d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Thu, 9 Apr 2020 19:23:49 +0200 Subject: [PATCH] checker: check enum --- vlib/v/ast/ast.v | 11 +++++++++-- vlib/v/checker/checker.v | 23 ++++++++++++++++++++--- vlib/v/fmt/fmt.v | 13 +++++++++++-- vlib/v/gen/cgen.v | 26 ++++++++++++++------------ vlib/v/parser/parser.v | 13 +++++++++---- 5 files changed, 63 insertions(+), 23 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 60bdec98bc..1645c65e12 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -494,12 +494,19 @@ mut: typ table.Type } +pub struct EnumField { + name string + pos token.Position + exprs []Expr +} + pub struct EnumDecl { pub: name string is_pub bool - vals []string - default_exprs []Expr + fields []EnumField + // vals []string + // default_exprs []Expr } pub struct AliasTypeDecl { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 67e85bde97..26a32708b2 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -560,6 +560,20 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) { } } +pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) { + for field in decl.fields { + for expr in field.exprs { + match expr { + ast.IntegerLiteral {} + ast.PrefixExpr {} + else { + c.error("default value for enum has to be an integer", field.pos) + } + } + } + } +} + pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) { c.expected_type = table.none_type // TODO a hack to make `x := if ... work` if assign_stmt.left.len > assign_stmt.right.len { @@ -737,9 +751,6 @@ fn (c mut Checker) stmt(node ast.Stmt) { c.stmts(it.else_stmts) } } - ast.DeferStmt { - c.stmts(it.stmts) - } ast.ConstDecl { mut field_names := []string mut field_order := []int @@ -776,6 +787,12 @@ fn (c mut Checker) stmt(node ast.Stmt) { it.fields = ordered_fields } } + ast.DeferStmt { + c.stmts(it.stmts) + } + ast.EnumDecl { + c.enum_decl(it) + } ast.ExprStmt { etype := c.expr(it.expr) c.expected_type = table.void_type diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index a0baa447a3..0d1e0aa250 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -208,8 +208,17 @@ fn (f mut Fmt) stmt(node ast.Stmt) { } name := it.name.after('.') f.writeln('enum $name {') - for val in it.vals { - f.writeln('\t' + val) + for field in it.fields { + f.write('\t$field.name') + if field.exprs.len > 0 { + f.write(' = ') + for expr in field.exprs { + f.expr(expr) + } + f.writeln(',') + } else { + f.writeln('') + } } f.writeln('}\n') } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 0423486733..559ac3e3bd 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -363,21 +363,23 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.defer_stmts << defer_stmt } ast.EnumDecl { - name := it.name.replace('.', '__') + enum_name := it.name.replace('.', '__') g.typedefs.writeln('typedef enum {') - for j, val in it.vals { - if j < it.default_exprs.len { - g.typedefs.write('\t${name}_$val = ') - pos := g.out.len - g.expr(it.default_exprs[j]) - expr := g.out.after(pos) - g.out.go_back(expr.len) - g.typedefs.writeln('$expr,') - } else { - g.typedefs.writeln('\t${name}_$val, // $j') + for field in it.fields { + g.typedefs.write('\t${enum_name}_$field.name') + if field.exprs.len > 0 { + g.typedefs.write(' = ') } + for expr in field.exprs { + pos := g.out.len + g.expr(expr) + expr_str := g.out.after(pos) + g.out.go_back(expr_str.len) + g.typedefs.write('$expr_str') + } + g.typedefs.writeln(',') } - g.typedefs.writeln('} $name;\n') + g.typedefs.writeln('} $enum_name;\n') } ast.ExprStmt { g.expr(it.expr) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index e158384bdd..88e96f5266 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1848,15 +1848,19 @@ fn (p mut Parser) enum_decl() ast.EnumDecl { name := p.prepend_mod(p.check_name()) p.check(.lcbr) mut vals := []string - mut default_exprs := []ast.Expr + // mut default_exprs := []ast.Expr + mut fields := []ast.EnumField for p.tok.kind != .eof && p.tok.kind != .rcbr { val := p.check_name() + pos := p.tok.position() vals << val + mut exprs := []ast.Expr // p.warn('enum val $val') if p.tok.kind == .assign { p.next() - default_exprs << p.expr(0) + exprs << p.expr(0) } + fields << ast.EnumField{val, pos, exprs} // Allow commas after enum, helpful for // enum Color { // r,g,b @@ -1876,8 +1880,9 @@ fn (p mut Parser) enum_decl() ast.EnumDecl { return ast.EnumDecl{ name: name is_pub: is_pub - vals: vals - default_exprs: default_exprs + // vals: vals + // default_exprs: default_exprs + fields: fields } }