checker: check enum

pull/4321/head
Daniel Däschle 2020-04-09 19:23:49 +02:00 committed by GitHub
parent 6ac64c8586
commit 320fad49c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 23 deletions

View File

@ -494,12 +494,19 @@ mut:
typ table.Type typ table.Type
} }
pub struct EnumField {
name string
pos token.Position
exprs []Expr
}
pub struct EnumDecl { pub struct EnumDecl {
pub: pub:
name string name string
is_pub bool is_pub bool
vals []string fields []EnumField
default_exprs []Expr // vals []string
// default_exprs []Expr
} }
pub struct AliasTypeDecl { pub struct AliasTypeDecl {

View File

@ -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) { 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` c.expected_type = table.none_type // TODO a hack to make `x := if ... work`
if assign_stmt.left.len > assign_stmt.right.len { 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) c.stmts(it.else_stmts)
} }
} }
ast.DeferStmt {
c.stmts(it.stmts)
}
ast.ConstDecl { ast.ConstDecl {
mut field_names := []string mut field_names := []string
mut field_order := []int mut field_order := []int
@ -776,6 +787,12 @@ fn (c mut Checker) stmt(node ast.Stmt) {
it.fields = ordered_fields it.fields = ordered_fields
} }
} }
ast.DeferStmt {
c.stmts(it.stmts)
}
ast.EnumDecl {
c.enum_decl(it)
}
ast.ExprStmt { ast.ExprStmt {
etype := c.expr(it.expr) etype := c.expr(it.expr)
c.expected_type = table.void_type c.expected_type = table.void_type

View File

@ -208,8 +208,17 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
} }
name := it.name.after('.') name := it.name.after('.')
f.writeln('enum $name {') f.writeln('enum $name {')
for val in it.vals { for field in it.fields {
f.writeln('\t' + val) 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') f.writeln('}\n')
} }

View File

@ -363,21 +363,23 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.defer_stmts << defer_stmt g.defer_stmts << defer_stmt
} }
ast.EnumDecl { ast.EnumDecl {
name := it.name.replace('.', '__') enum_name := it.name.replace('.', '__')
g.typedefs.writeln('typedef enum {') g.typedefs.writeln('typedef enum {')
for j, val in it.vals { for field in it.fields {
if j < it.default_exprs.len { g.typedefs.write('\t${enum_name}_$field.name')
g.typedefs.write('\t${name}_$val = ') if field.exprs.len > 0 {
pos := g.out.len g.typedefs.write(' = ')
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 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 { ast.ExprStmt {
g.expr(it.expr) g.expr(it.expr)

View File

@ -1848,15 +1848,19 @@ fn (p mut Parser) enum_decl() ast.EnumDecl {
name := p.prepend_mod(p.check_name()) name := p.prepend_mod(p.check_name())
p.check(.lcbr) p.check(.lcbr)
mut vals := []string 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 { for p.tok.kind != .eof && p.tok.kind != .rcbr {
val := p.check_name() val := p.check_name()
pos := p.tok.position()
vals << val vals << val
mut exprs := []ast.Expr
// p.warn('enum val $val') // p.warn('enum val $val')
if p.tok.kind == .assign { if p.tok.kind == .assign {
p.next() p.next()
default_exprs << p.expr(0) exprs << p.expr(0)
} }
fields << ast.EnumField{val, pos, exprs}
// Allow commas after enum, helpful for // Allow commas after enum, helpful for
// enum Color { // enum Color {
// r,g,b // r,g,b
@ -1876,8 +1880,9 @@ fn (p mut Parser) enum_decl() ast.EnumDecl {
return ast.EnumDecl{ return ast.EnumDecl{
name: name name: name
is_pub: is_pub is_pub: is_pub
vals: vals // vals: vals
default_exprs: default_exprs // default_exprs: default_exprs
fields: fields
} }
} }