parser: fix enum default value in struct

* parser: fix enum default value in struct

* Add a test for the enum default values in structs.

* Fix compilation of vfmt.

* Run vfmt over enum_default_value_in_struct_test.v

* Cleanup spurious , in vfmt output for enum declarations

Co-authored-by: Delyan Angelov <delian66@gmail.com>
pull/4364/head
Daniel Däschle 2020-04-12 12:35:54 +02:00 committed by GitHub
parent 0ced7116b6
commit 79dad0bca9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 30 deletions

View File

@ -144,7 +144,6 @@ fn main() {
} }
exit(1) exit(1)
} }
println('vfmt done')
} }
fn (foptions &FormatOptions) format_file(file string) { fn (foptions &FormatOptions) format_file(file string) {

View File

@ -104,7 +104,8 @@ pub:
name string name string
pos token.Position pos token.Position
comment Comment comment Comment
default_expr string // token literal //Expr default_expr Expr
has_default_expr bool
attr string attr string
mut: mut:
typ table.Type typ table.Type

View File

@ -136,6 +136,9 @@ pub fn (x Expr) str() string {
TypeOf { TypeOf {
return 'typeof(${it.expr.str()})' return 'typeof(${it.expr.str()})'
} }
EnumVal {
return '.${it.val}'
}
CallExpr { CallExpr {
sargs := args2str(it.args) sargs := args2str(it.args)
if it.is_method { if it.is_method {

View File

@ -216,10 +216,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
if field.has_expr { if field.has_expr {
f.write(' = ') f.write(' = ')
f.expr(field.expr) f.expr(field.expr)
f.writeln(',')
} else {
f.writeln('')
} }
f.writeln('')
} }
f.writeln('}\n') f.writeln('}\n')
} }
@ -407,8 +405,8 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) {
f.write('\t$field.name ') f.write('\t$field.name ')
f.write(strings.repeat(` `, max - field.name.len)) f.write(strings.repeat(` `, max - field.name.len))
f.write(f.type_to_str(field.typ)) f.write(f.type_to_str(field.typ))
if field.default_expr != '' { if field.has_default_expr {
f.write(' = $field.default_expr') f.write(' = ${field.default_expr.str()}')
} }
// f.write('// $field.pos.line_nr') // f.write('// $field.pos.line_nr')
if field.comment.text != '' && field.comment.pos.line_nr == field.pos.line_nr { if field.comment.text != '' && field.comment.pos.line_nr == field.pos.line_nr {

View File

@ -1077,10 +1077,9 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write("'$it.val'") g.write("'$it.val'")
} }
ast.EnumVal { ast.EnumVal {
// g.write('/*EnumVal*/${it.mod}${it.enum_name}_$it.val') // g.write('${it.mod}${it.enum_name}_$it.val')
styp := g.typ(it.typ) styp := g.typ(it.typ)
g.write(styp) g.write('${styp}_$it.val')
g.write('_$it.val')
} }
ast.FloatLiteral { ast.FloatLiteral {
g.write(it.val) g.write(it.val)
@ -1971,17 +1970,17 @@ fn (g mut Gen) const_decl_simple_define(name, val string) {
g.definitions.writeln(val) g.definitions.writeln(val)
} }
fn (g mut Gen) struct_init(it ast.StructInit) { fn (g mut Gen) struct_init(struct_init ast.StructInit) {
mut info := table.Struct{} mut info := table.Struct{}
mut is_struct := false mut is_struct := false
sym := g.table.get_type_symbol(it.typ) sym := g.table.get_type_symbol(struct_init.typ)
if sym.kind == .struct_ { if sym.kind == .struct_ {
is_struct = true is_struct = true
info = sym.info as table.Struct info = sym.info as table.Struct
} }
// info := g.table.get_type_symbol(it.typ).info as table.Struct // info := g.table.get_type_symbol(it.typ).info as table.Struct
// println(info.fields.len) // println(info.fields.len)
styp := g.typ(it.typ) styp := g.typ(struct_init.typ)
is_amp := g.is_amp is_amp := g.is_amp
if is_amp { if is_amp {
g.out.go_back(1) // delete the & already generated in `prefix_expr() g.out.go_back(1) // delete the & already generated in `prefix_expr()
@ -1991,20 +1990,20 @@ fn (g mut Gen) struct_init(it ast.StructInit) {
} }
mut fields := []string mut fields := []string
mut inited_fields := []string // TODO this is done in checker, move to ast node mut inited_fields := []string // TODO this is done in checker, move to ast node
if it.fields.len == 0 && it.exprs.len > 0 { if struct_init.fields.len == 0 && struct_init.exprs.len > 0 {
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser. // Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
for f in info.fields { for f in info.fields {
fields << f.name fields << f.name
} }
} else { } else {
fields = it.fields fields = struct_init.fields
} }
// / User set fields // User set fields
for i, field in fields { for i, field in fields {
field_name := c_name(field) field_name := c_name(field)
inited_fields << field inited_fields << field
g.write('\t.$field_name = ') g.write('\t.$field_name = ')
g.expr_with_cast(it.exprs[i], it.expr_types[i], it.expected_types[i]) g.expr_with_cast(struct_init.exprs[i], struct_init.expr_types[i], struct_init.expected_types[i])
g.writeln(',') g.writeln(',')
} }
// The rest of the fields are zeroed. // The rest of the fields are zeroed.
@ -2018,11 +2017,16 @@ fn (g mut Gen) struct_init(it ast.StructInit) {
continue continue
} }
field_name := c_name(field.name) field_name := c_name(field.name)
zero := if field.default_val != '' { field.default_val } else { g.type_default(field.typ) } if field.has_default_expr {
g.writeln('\t.$field_name = $zero,') // zer0') g.expr(field.default_expr)
g.writeln(',')
} else {
zero := g.type_default(field.typ)
g.writeln('\t.$field_name = $zero,')
} }
} }
if it.fields.len == 0 && info.fields.len == 0 { }
if struct_init.fields.len == 0 && info.fields.len == 0 {
g.write('0') g.write('0')
} }
g.write('}') g.write('}')

View File

@ -1555,13 +1555,20 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
println('XXXX' + s.str()) println('XXXX' + s.str())
} }
*/ */
mut default_expr := '' // ast.Expr{} mut default_expr := ast.Expr{}
mut has_default_expr := false
if p.tok.kind == .assign { if p.tok.kind == .assign {
// Default value // Default value
p.next() p.next()
default_expr = p.tok.lit // default_expr = p.tok.lit
p.expr(0) // p.expr(0)
// default_expr = p.expr(0) default_expr = p.expr(0)
match default_expr {
ast.EnumVal { it.typ = typ }
// TODO: implement all types??
else {}
}
has_default_expr = true
} }
if p.tok.kind == .comment { if p.tok.kind == .comment {
comment = p.comment() comment = p.comment()
@ -1572,11 +1579,13 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
typ: typ typ: typ
comment: comment comment: comment
default_expr: default_expr default_expr: default_expr
has_default_expr: has_default_expr
} }
fields << table.Field{ fields << table.Field{
name: field_name name: field_name
typ: typ typ: typ
default_val: default_expr default_expr: default_expr
has_default_expr: has_default_expr
} }
// println('struct field $ti.name $field_name') // println('struct field $ti.name $field_name')
} }

View File

@ -559,6 +559,8 @@ pub:
name string name string
mut: mut:
typ Type typ Type
default_expr ast.Expr
has_default_expr bool
default_val string default_val string
} }

View File

@ -0,0 +1,28 @@
pub enum MyEnum {
first = 20
second
third
}
pub struct MyStruct {
mut:
e MyEnum = .second
}
fn test_enum_first_value() {
assert MyEnum.first == 20
}
fn test_enum_default_value() {
d := MyStruct{}
assert int(d.e) == 21
assert 'd.e: $d.e | int(d.e): ${int(d.e).str()}' == 'd.e: second | int(d.e): 21'
}
fn test_enum_non_default_value() {
t := MyStruct{
e: .third
}
assert int(t.e) == 22
assert 't.e: $t.e | int(t.e): ${int(t.e).str()}' == 't.e: third | int(t.e): 22'
}