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
parent
0ced7116b6
commit
79dad0bca9
|
@ -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) {
|
||||||
|
|
|
@ -101,13 +101,14 @@ pub:
|
||||||
|
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
pos token.Position
|
pos token.Position
|
||||||
comment Comment
|
comment Comment
|
||||||
default_expr string // token literal //Expr
|
default_expr Expr
|
||||||
attr string
|
has_default_expr bool
|
||||||
|
attr string
|
||||||
mut:
|
mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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('}')
|
||||||
|
|
|
@ -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')
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
}
|
Loading…
Reference in New Issue