From 79dad0bca97efd0cb1b74976160cddd3a6123526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Sun, 12 Apr 2020 12:35:54 +0200 Subject: [PATCH] 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 --- cmd/tools/vfmt.v | 1 - vlib/v/ast/ast.v | 13 ++++---- vlib/v/ast/str.v | 3 ++ vlib/v/fmt/fmt.v | 8 ++--- vlib/v/gen/cgen.v | 30 +++++++++++-------- vlib/v/parser/parser.v | 19 ++++++++---- vlib/v/table/atypes.v | 2 ++ .../tests/enum_default_value_in_struct_test.v | 28 +++++++++++++++++ 8 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 vlib/v/tests/enum_default_value_in_struct_test.v diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index 353828c541..f304daa107 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -144,7 +144,6 @@ fn main() { } exit(1) } - println('vfmt done') } fn (foptions &FormatOptions) format_file(file string) { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index a2ab93a153..904170faaf 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -101,13 +101,14 @@ pub: pub struct StructField { pub: - name string - pos token.Position - comment Comment - default_expr string // token literal //Expr - attr string + name string + pos token.Position + comment Comment + default_expr Expr + has_default_expr bool + attr string mut: - typ table.Type + typ table.Type } pub struct Field { diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index 92b593f3c3..8503f723df 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -136,6 +136,9 @@ pub fn (x Expr) str() string { TypeOf { return 'typeof(${it.expr.str()})' } + EnumVal { + return '.${it.val}' + } CallExpr { sargs := args2str(it.args) if it.is_method { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 580203a6c9..bfd74413dc 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -216,10 +216,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) { if field.has_expr { f.write(' = ') f.expr(field.expr) - f.writeln(',') - } else { - f.writeln('') } + f.writeln('') } f.writeln('}\n') } @@ -407,8 +405,8 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) { f.write('\t$field.name ') f.write(strings.repeat(` `, max - field.name.len)) f.write(f.type_to_str(field.typ)) - if field.default_expr != '' { - f.write(' = $field.default_expr') + if field.has_default_expr { + f.write(' = ${field.default_expr.str()}') } // f.write('// $field.pos.line_nr') if field.comment.text != '' && field.comment.pos.line_nr == field.pos.line_nr { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 704fa134bf..9ab5c40ba0 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1077,10 +1077,9 @@ fn (g mut Gen) expr(node ast.Expr) { g.write("'$it.val'") } 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) - g.write(styp) - g.write('_$it.val') + g.write('${styp}_$it.val') } ast.FloatLiteral { g.write(it.val) @@ -1971,17 +1970,17 @@ fn (g mut Gen) const_decl_simple_define(name, val string) { 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 is_struct := false - sym := g.table.get_type_symbol(it.typ) + sym := g.table.get_type_symbol(struct_init.typ) if sym.kind == .struct_ { is_struct = true info = sym.info as table.Struct } // info := g.table.get_type_symbol(it.typ).info as table.Struct // println(info.fields.len) - styp := g.typ(it.typ) + styp := g.typ(struct_init.typ) is_amp := g.is_amp if is_amp { 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 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. for f in info.fields { fields << f.name } } else { - fields = it.fields + fields = struct_init.fields } - // / User set fields + // User set fields for i, field in fields { field_name := c_name(field) inited_fields << field 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(',') } // The rest of the fields are zeroed. @@ -2018,11 +2017,16 @@ fn (g mut Gen) struct_init(it ast.StructInit) { continue } field_name := c_name(field.name) - zero := if field.default_val != '' { field.default_val } else { g.type_default(field.typ) } - g.writeln('\t.$field_name = $zero,') // zer0') + if field.has_default_expr { + 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('}') diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index e8bf91bf04..19dad0a727 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1555,13 +1555,20 @@ fn (p mut Parser) struct_decl() ast.StructDecl { println('XXXX' + s.str()) } */ - mut default_expr := '' // ast.Expr{} + mut default_expr := ast.Expr{} + mut has_default_expr := false if p.tok.kind == .assign { // Default value p.next() - default_expr = p.tok.lit - p.expr(0) - // default_expr = p.expr(0) + // default_expr = p.tok.lit + // 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 { comment = p.comment() @@ -1572,11 +1579,13 @@ fn (p mut Parser) struct_decl() ast.StructDecl { typ: typ comment: comment default_expr: default_expr + has_default_expr: has_default_expr } fields << table.Field{ name: field_name typ: typ - default_val: default_expr + default_expr: default_expr + has_default_expr: has_default_expr } // println('struct field $ti.name $field_name') } diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index 2e877b00ce..1125f022a3 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -559,6 +559,8 @@ pub: name string mut: typ Type + default_expr ast.Expr + has_default_expr bool default_val string } diff --git a/vlib/v/tests/enum_default_value_in_struct_test.v b/vlib/v/tests/enum_default_value_in_struct_test.v new file mode 100644 index 0000000000..b3f3af6643 --- /dev/null +++ b/vlib/v/tests/enum_default_value_in_struct_test.v @@ -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' +}