mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
v: allow shared anon struct + fix shared struct field initialization with no default value (#23448)
This commit is contained in:
parent
ae8109545e
commit
8f0242e6af
6 changed files with 69 additions and 4 deletions
|
@ -169,6 +169,7 @@ pub mut:
|
||||||
is_minify bool
|
is_minify bool
|
||||||
is_anon bool
|
is_anon bool
|
||||||
is_generic bool
|
is_generic bool
|
||||||
|
is_shared bool
|
||||||
has_option bool // contains any option field
|
has_option bool // contains any option field
|
||||||
generic_types []Type
|
generic_types []Type
|
||||||
concrete_types []Type
|
concrete_types []Type
|
||||||
|
|
|
@ -153,6 +153,9 @@ fn (mut f Fmt) write_anon_struct_field_decl(field_typ ast.Type, field_anon_decl
|
||||||
info := sym.info as ast.Struct
|
info := sym.info as ast.Struct
|
||||||
if info.is_anon {
|
if info.is_anon {
|
||||||
f.indent++
|
f.indent++
|
||||||
|
if info.is_shared {
|
||||||
|
f.write('shared ')
|
||||||
|
}
|
||||||
f.struct_decl(field_anon_decl, true)
|
f.struct_decl(field_anon_decl, true)
|
||||||
f.indent--
|
f.indent--
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1008,7 +1008,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin
|
||||||
} else {
|
} else {
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
base_fmt := g.type_to_fmt(g.unwrap_generic(field.typ))
|
mut base_typ := g.unwrap_generic(field.typ)
|
||||||
|
if base_typ.has_flag(.shared_f) {
|
||||||
|
base_typ = base_typ.clear_flag(.shared_f).deref()
|
||||||
|
}
|
||||||
|
base_fmt := g.type_to_fmt(base_typ)
|
||||||
is_opt_field := field.typ.has_flag(.option)
|
is_opt_field := field.typ.has_flag(.option)
|
||||||
|
|
||||||
// manage prefix and quote symbol for the filed
|
// manage prefix and quote symbol for the filed
|
||||||
|
@ -1194,7 +1198,7 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.
|
||||||
if !field_type.is_ptr() && field_type.has_option_or_result() {
|
if !field_type.is_ptr() && field_type.has_option_or_result() {
|
||||||
method_str = '(*(${sym.name}*)it${op}${final_field_name}.data)'
|
method_str = '(*(${sym.name}*)it${op}${final_field_name}.data)'
|
||||||
} else {
|
} else {
|
||||||
method_str = 'it${op}${final_field_name}'
|
method_str = 'it${op}${final_field_name}${sufix}'
|
||||||
}
|
}
|
||||||
if sym.kind == .bool {
|
if sym.kind == .bool {
|
||||||
return '${method_str} ? _SLIT("true") : _SLIT("false")', false
|
return '${method_str} ? _SLIT("true") : _SLIT("false")', false
|
||||||
|
|
|
@ -414,6 +414,14 @@ fn (mut g Gen) get_embed_field_name(field_type ast.Type, field_name string) stri
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) init_shared_field(field ast.StructField) {
|
||||||
|
field_typ := field.typ.deref()
|
||||||
|
shared_styp := g.styp(field_typ)
|
||||||
|
g.write('(${shared_styp}*)__dup${shared_styp}(&(${shared_styp}){.mtx= {0}, .val=')
|
||||||
|
g.write(g.type_default(field_typ.clear_flag(.shared_f)))
|
||||||
|
g.write('}, sizeof(${shared_styp}))')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
||||||
old_inside_cast_in_heap := g.inside_cast_in_heap
|
old_inside_cast_in_heap := g.inside_cast_in_heap
|
||||||
g.inside_cast_in_heap = 0
|
g.inside_cast_in_heap = 0
|
||||||
|
@ -428,6 +436,11 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
||||||
return false
|
return false
|
||||||
} else if !field.has_default_expr {
|
} else if !field.has_default_expr {
|
||||||
mut has_option_field := false
|
mut has_option_field := false
|
||||||
|
if sym.info.is_shared || field.typ.has_flag(.shared_f) {
|
||||||
|
g.write('.${field_name} = ')
|
||||||
|
g.init_shared_field(field)
|
||||||
|
return true
|
||||||
|
}
|
||||||
for fd in sym.info.fields {
|
for fd in sym.info.fields {
|
||||||
if fd.typ.has_flag(.option) {
|
if fd.typ.has_flag(.option) {
|
||||||
has_option_field = true
|
has_option_field = true
|
||||||
|
@ -520,6 +533,8 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write('}')
|
g.write('}')
|
||||||
|
} else if field.typ.has_flag(.shared_f) {
|
||||||
|
g.init_shared_field(field)
|
||||||
} else {
|
} else {
|
||||||
g.write(g.type_default(field.typ))
|
g.write(g.type_default(field.typ))
|
||||||
}
|
}
|
||||||
|
@ -570,7 +585,11 @@ fn (mut g Gen) struct_decl(s ast.Struct, name string, is_anon bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_anon {
|
if is_anon {
|
||||||
g.type_definitions.write_string('\t${name} ')
|
if s.is_shared {
|
||||||
|
g.type_definitions.write_string('\t__shared__${name}* ')
|
||||||
|
} else {
|
||||||
|
g.type_definitions.write_string('\t${name} ')
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} else if s.is_union {
|
} else if s.is_union {
|
||||||
if g.is_cc_msvc && aligned_attr != '' {
|
if g.is_cc_msvc && aligned_attr != '' {
|
||||||
|
|
|
@ -13,10 +13,15 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
||||||
attrs := p.attrs
|
attrs := p.attrs
|
||||||
start_pos := p.tok.pos()
|
start_pos := p.tok.pos()
|
||||||
mut is_pub := p.tok.kind == .key_pub
|
mut is_pub := p.tok.kind == .key_pub
|
||||||
|
mut is_shared := p.tok.kind == .key_shared
|
||||||
if is_pub {
|
if is_pub {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
if is_anon {
|
if is_anon {
|
||||||
|
if is_shared {
|
||||||
|
p.register_auto_import('sync')
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
is_pub = true
|
is_pub = true
|
||||||
}
|
}
|
||||||
is_union := p.tok.kind == .key_union
|
is_union := p.tok.kind == .key_union
|
||||||
|
@ -236,12 +241,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
||||||
// struct field
|
// struct field
|
||||||
field_name = p.check_name()
|
field_name = p.check_name()
|
||||||
p.inside_struct_field_decl = true
|
p.inside_struct_field_decl = true
|
||||||
if p.tok.kind == .key_struct {
|
if p.tok.kind == .key_struct
|
||||||
|
|| (p.tok.kind == .key_shared && p.peek_tok.kind == .key_struct) {
|
||||||
// Anon structs
|
// Anon structs
|
||||||
|
field_is_shared := p.tok.kind == .key_shared
|
||||||
p.anon_struct_decl = p.struct_decl(true)
|
p.anon_struct_decl = p.struct_decl(true)
|
||||||
p.anon_struct_decl.language = language
|
p.anon_struct_decl.language = language
|
||||||
// Find the registered anon struct type, it was registered above in `p.struct_decl()`
|
// Find the registered anon struct type, it was registered above in `p.struct_decl()`
|
||||||
typ = p.table.find_type_idx(p.anon_struct_decl.name)
|
typ = p.table.find_type_idx(p.anon_struct_decl.name)
|
||||||
|
if field_is_shared {
|
||||||
|
typ = typ.set_flag(.shared_f)
|
||||||
|
typ = typ.set_nr_muls(1)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
start_type_pos := p.tok.pos()
|
start_type_pos := p.tok.pos()
|
||||||
typ = p.parse_type()
|
typ = p.parse_type()
|
||||||
|
@ -379,6 +390,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
||||||
generic_types: generic_types
|
generic_types: generic_types
|
||||||
attrs: attrs
|
attrs: attrs
|
||||||
is_anon: is_anon
|
is_anon: is_anon
|
||||||
|
is_shared: is_shared
|
||||||
has_option: has_option
|
has_option: has_option
|
||||||
}
|
}
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
|
|
26
vlib/v/tests/structs/struct_field_shared_test.v
Normal file
26
vlib/v/tests/structs/struct_field_shared_test.v
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
struct Foo {
|
||||||
|
bar shared struct {
|
||||||
|
mut:
|
||||||
|
foo int
|
||||||
|
bar int
|
||||||
|
}
|
||||||
|
baz shared int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
assert Foo{}.str() == 'Foo{
|
||||||
|
bar: struct {
|
||||||
|
foo: 0
|
||||||
|
bar: 0
|
||||||
|
}
|
||||||
|
baz: 0
|
||||||
|
}'
|
||||||
|
mut t := Foo{}
|
||||||
|
lock t.bar {
|
||||||
|
t.bar.foo = 1
|
||||||
|
t.bar.bar = 2
|
||||||
|
}
|
||||||
|
rlock t.bar {
|
||||||
|
assert t.bar.foo + t.bar.bar == 3
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue