Skip to content

Commit 8f0242e

Browse files
authored
v: allow shared anon struct + fix shared struct field initialization with no default value (#23448)
1 parent ae81095 commit 8f0242e

6 files changed

Lines changed: 69 additions & 4 deletions

File tree

‎vlib/v/ast/types.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub mut:
169169
is_minify bool
170170
is_anon bool
171171
is_generic bool
172+
is_shared bool
172173
has_option bool // contains any option field
173174
generic_types []Type
174175
concrete_types []Type

‎vlib/v/fmt/struct.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ fn (mut f Fmt) write_anon_struct_field_decl(field_typ ast.Type, field_anon_decl
153153
info := sym.info as ast.Struct
154154
if info.is_anon {
155155
f.indent++
156+
if info.is_shared {
157+
f.write('shared ')
158+
}
156159
f.struct_decl(field_anon_decl, true)
157160
f.indent--
158161
return true

‎vlib/v/gen/c/auto_str_methods.v‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin
10081008
} else {
10091009
''
10101010
}
1011-
base_fmt := g.type_to_fmt(g.unwrap_generic(field.typ))
1011+
mut base_typ := g.unwrap_generic(field.typ)
1012+
if base_typ.has_flag(.shared_f) {
1013+
base_typ = base_typ.clear_flag(.shared_f).deref()
1014+
}
1015+
base_fmt := g.type_to_fmt(base_typ)
10121016
is_opt_field := field.typ.has_flag(.option)
10131017

10141018
// 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.
11941198
if !field_type.is_ptr() && field_type.has_option_or_result() {
11951199
method_str = '(*(${sym.name}*)it${op}${final_field_name}.data)'
11961200
} else {
1197-
method_str = 'it${op}${final_field_name}'
1201+
method_str = 'it${op}${final_field_name}${sufix}'
11981202
}
11991203
if sym.kind == .bool {
12001204
return '${method_str} ? _SLIT("true") : _SLIT("false")', false

‎vlib/v/gen/c/struct.v‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,14 @@ fn (mut g Gen) get_embed_field_name(field_type ast.Type, field_name string) stri
414414
return s
415415
}
416416

417+
fn (mut g Gen) init_shared_field(field ast.StructField) {
418+
field_typ := field.typ.deref()
419+
shared_styp := g.styp(field_typ)
420+
g.write('(${shared_styp}*)__dup${shared_styp}(&(${shared_styp}){.mtx= {0}, .val=')
421+
g.write(g.type_default(field_typ.clear_flag(.shared_f)))
422+
g.write('}, sizeof(${shared_styp}))')
423+
}
424+
417425
fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
418426
old_inside_cast_in_heap := g.inside_cast_in_heap
419427
g.inside_cast_in_heap = 0
@@ -428,6 +436,11 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
428436
return false
429437
} else if !field.has_default_expr {
430438
mut has_option_field := false
439+
if sym.info.is_shared || field.typ.has_flag(.shared_f) {
440+
g.write('.${field_name} = ')
441+
g.init_shared_field(field)
442+
return true
443+
}
431444
for fd in sym.info.fields {
432445
if fd.typ.has_flag(.option) {
433446
has_option_field = true
@@ -520,6 +533,8 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
520533
}
521534
}
522535
g.write('}')
536+
} else if field.typ.has_flag(.shared_f) {
537+
g.init_shared_field(field)
523538
} else {
524539
g.write(g.type_default(field.typ))
525540
}
@@ -570,7 +585,11 @@ fn (mut g Gen) struct_decl(s ast.Struct, name string, is_anon bool) {
570585
}
571586
}
572587
if is_anon {
573-
g.type_definitions.write_string('\t${name} ')
588+
if s.is_shared {
589+
g.type_definitions.write_string('\t__shared__${name}* ')
590+
} else {
591+
g.type_definitions.write_string('\t${name} ')
592+
}
574593
return
575594
} else if s.is_union {
576595
if g.is_cc_msvc && aligned_attr != '' {

‎vlib/v/parser/struct.v‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
1313
attrs := p.attrs
1414
start_pos := p.tok.pos()
1515
mut is_pub := p.tok.kind == .key_pub
16+
mut is_shared := p.tok.kind == .key_shared
1617
if is_pub {
1718
p.next()
1819
}
1920
if is_anon {
21+
if is_shared {
22+
p.register_auto_import('sync')
23+
p.next()
24+
}
2025
is_pub = true
2126
}
2227
is_union := p.tok.kind == .key_union
@@ -236,12 +241,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
236241
// struct field
237242
field_name = p.check_name()
238243
p.inside_struct_field_decl = true
239-
if p.tok.kind == .key_struct {
244+
if p.tok.kind == .key_struct
245+
|| (p.tok.kind == .key_shared && p.peek_tok.kind == .key_struct) {
240246
// Anon structs
247+
field_is_shared := p.tok.kind == .key_shared
241248
p.anon_struct_decl = p.struct_decl(true)
242249
p.anon_struct_decl.language = language
243250
// Find the registered anon struct type, it was registered above in `p.struct_decl()`
244251
typ = p.table.find_type_idx(p.anon_struct_decl.name)
252+
if field_is_shared {
253+
typ = typ.set_flag(.shared_f)
254+
typ = typ.set_nr_muls(1)
255+
}
245256
} else {
246257
start_type_pos := p.tok.pos()
247258
typ = p.parse_type()
@@ -379,6 +390,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
379390
generic_types: generic_types
380391
attrs: attrs
381392
is_anon: is_anon
393+
is_shared: is_shared
382394
has_option: has_option
383395
}
384396
is_pub: is_pub
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
struct Foo {
2+
bar shared struct {
3+
mut:
4+
foo int
5+
bar int
6+
}
7+
baz shared int
8+
}
9+
10+
fn test_main() {
11+
assert Foo{}.str() == 'Foo{
12+
bar: struct {
13+
foo: 0
14+
bar: 0
15+
}
16+
baz: 0
17+
}'
18+
mut t := Foo{}
19+
lock t.bar {
20+
t.bar.foo = 1
21+
t.bar.bar = 2
22+
}
23+
rlock t.bar {
24+
assert t.bar.foo + t.bar.bar == 3
25+
}
26+
}

0 commit comments

Comments
 (0)