mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32: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_anon bool
|
||||
is_generic bool
|
||||
is_shared bool
|
||||
has_option bool // contains any option field
|
||||
generic_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
|
||||
if info.is_anon {
|
||||
f.indent++
|
||||
if info.is_shared {
|
||||
f.write('shared ')
|
||||
}
|
||||
f.struct_decl(field_anon_decl, true)
|
||||
f.indent--
|
||||
return true
|
||||
|
|
|
@ -1008,7 +1008,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin
|
|||
} 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)
|
||||
|
||||
// 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() {
|
||||
method_str = '(*(${sym.name}*)it${op}${final_field_name}.data)'
|
||||
} else {
|
||||
method_str = 'it${op}${final_field_name}'
|
||||
method_str = 'it${op}${final_field_name}${sufix}'
|
||||
}
|
||||
if sym.kind == .bool {
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
old_inside_cast_in_heap := g.inside_cast_in_heap
|
||||
g.inside_cast_in_heap = 0
|
||||
|
@ -428,6 +436,11 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
|||
return false
|
||||
} else if !field.has_default_expr {
|
||||
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 {
|
||||
if fd.typ.has_flag(.option) {
|
||||
has_option_field = true
|
||||
|
@ -520,6 +533,8 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
|||
}
|
||||
}
|
||||
g.write('}')
|
||||
} else if field.typ.has_flag(.shared_f) {
|
||||
g.init_shared_field(field)
|
||||
} else {
|
||||
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 {
|
||||
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
|
||||
} else if s.is_union {
|
||||
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
|
||||
start_pos := p.tok.pos()
|
||||
mut is_pub := p.tok.kind == .key_pub
|
||||
mut is_shared := p.tok.kind == .key_shared
|
||||
if is_pub {
|
||||
p.next()
|
||||
}
|
||||
if is_anon {
|
||||
if is_shared {
|
||||
p.register_auto_import('sync')
|
||||
p.next()
|
||||
}
|
||||
is_pub = true
|
||||
}
|
||||
is_union := p.tok.kind == .key_union
|
||||
|
@ -236,12 +241,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||
// struct field
|
||||
field_name = p.check_name()
|
||||
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
|
||||
field_is_shared := p.tok.kind == .key_shared
|
||||
p.anon_struct_decl = p.struct_decl(true)
|
||||
p.anon_struct_decl.language = language
|
||||
// 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)
|
||||
if field_is_shared {
|
||||
typ = typ.set_flag(.shared_f)
|
||||
typ = typ.set_nr_muls(1)
|
||||
}
|
||||
} else {
|
||||
start_type_pos := p.tok.pos()
|
||||
typ = p.parse_type()
|
||||
|
@ -379,6 +390,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||
generic_types: generic_types
|
||||
attrs: attrs
|
||||
is_anon: is_anon
|
||||
is_shared: is_shared
|
||||
has_option: has_option
|
||||
}
|
||||
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