1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen,js: support [autostr: allowrecurse] attribute, for allowing deep printing of data structures with pointer fields (trees, instead of graphs with cycles) (#16973)

This commit is contained in:
l-m 2023-01-14 20:30:39 +11:00 committed by GitHub
parent 7e05545a62
commit ca000292f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 2 deletions

View File

@ -860,6 +860,8 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string,
}
fn_body.writeln('\tstring res = str_intp( ${(info.fields.len - field_skips.len) * 4 + 3}, _MOV((StrIntpData[]){')
fn_body.writeln('\t\t{_SLIT("${clean_struct_v_type_name}{\\n"), 0, {.d_c=0}},')
allow_circular := info.attrs.any(it.name == 'autostr' && it.arg == 'allowrecurse')
mut is_first := true
for i, field in info.fields {
// Skip `str:skip` fields
@ -937,7 +939,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string,
}
}
// handle circular ref type of struct to the struct itself
if styp == field_styp {
if styp == field_styp && !allow_circular {
fn_body.write_string('${funcprefix}_SLIT("<circular>")')
} else {
// manage C charptr

View File

@ -712,6 +712,7 @@ fn (mut g JsGen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name st
fn_builder.writeln('\tlet res = /*struct name*/new string("${clean_struct_v_type_name}{\\n")')
allow_circular := info.attrs.any(it.name == 'autostr' && it.arg == 'allowrecurse')
for i, field in info.fields {
mut ptr_amp := if field.typ.is_ptr() { '&' } else { '' }
mut prefix := ''
@ -758,7 +759,7 @@ fn (mut g JsGen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name st
}
}
// handle circular ref type of struct to the struct itself
if styp == field_styp {
if styp == field_styp && !allow_circular {
fn_builder.write_string('res.str += new string("<circular>")')
} else {
// manage C charptr

View File

@ -0,0 +1,23 @@
[autostr: allowrecurse]
struct Node {
a &Node = unsafe { nil }
b &Node = unsafe { nil }
}
fn test_stringifying_a_value_of_a_struct_tagged_with_autostr_allowrecurse() {
abc := &Node{
a: &Node{
b: &Node{}
}
b: &Node{
a: &Node{}
}
}
// println(abc)
s := abc.str()
assert !s.contains('&<circular>')
assert s.contains('a: &Node{')
assert s.contains('a: &nil')
assert s.contains('b: &Node{')
assert s.contains('b: &nil')
}