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
}
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 {

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) {
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

View File

@ -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')
}

View File

@ -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)

View File

@ -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
}
}