diff --git a/vlib/compiler/fn.v b/vlib/compiler/fn.v index 8b59ef246e..d87f3dca24 100644 --- a/vlib/compiler/fn.v +++ b/vlib/compiler/fn.v @@ -70,6 +70,20 @@ fn (a []TypeInst) str() string { return r.str() } +fn (p mut Parser) find_var_or_const(name string) ?Var { + if p.known_var(name) { + return p.find_var(name) + } + if p.table.known_const(name) { + return p.table.find_const(name) + } + modname := p.prepend_mod(name) + if p.table.known_const(modname) { + return p.table.find_const(modname) + } + return none +} + fn (p &Parser) find_var(name string) ?Var { for i in 0 .. p.var_idx { if p.local_vars[i].name == name { diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 0fb7bc09cd..71d0d517f7 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -2150,11 +2150,13 @@ fn (p mut Parser) assoc() string { // println('assoc()') p.next() name := p.check_name() - var := p.find_var(name) or { + var := p.find_var_or_const(name) or { p.error('unknown variable `$name`') exit(1) } - p.mark_var_used(var) + if !var.is_const { + p.mark_var_used(var) + } p.check(.pipe) p.gen('($var.typ){') mut fields := []string// track the fields user is setting, the rest will be copied from the old object @@ -2177,7 +2179,7 @@ fn (p mut Parser) assoc() string { if f in fields { continue } - p.gen('.$f = ${name}.$f,') + p.gen('.$f = ${var.name}.$f,') } p.check(.rcbr) p.gen('}') diff --git a/vlib/compiler/tests/struct_test.v b/vlib/compiler/tests/struct_test.v index 07021b0df1..c9cb622347 100644 --- a/vlib/compiler/tests/struct_test.v +++ b/vlib/compiler/tests/struct_test.v @@ -111,19 +111,19 @@ fn test_reserved_keywords() { struct User2 { mut: name string -} +} fn test_mutable_fields() { mut u := User2{} u.name = 'Peter' assert u.name == 'Peter' -} +} struct Def { a int b int = 7 -} +} fn test_default_vals() { d := Def{} @@ -132,5 +132,25 @@ fn test_default_vals() { d2 := Def{10, 20} assert d2.a == 10 assert d2.b == 20 -} +} + +fn test_assoc_with_vars() { + def2 := Def { a: 12 } + merged := { def2 | a: 42 } + assert merged.a == 42 + assert merged.b == 7 +} + +const ( + const_def = Def { a: 100 } +) +fn test_assoc_with_constants() { + merged := { const_def | a: 42 } + assert merged.a == 42 + assert merged.b == 7 + + again := { const_def | b: 22 } + assert again.a == 100 + assert again.b == 22 +}