mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast, cgen: fix printing nested generic struct (#16758)
This commit is contained in:
parent
85b4af5440
commit
21d6bd930e
@ -1395,9 +1395,9 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
|
||||
}
|
||||
// types defined by the user
|
||||
// mod.submod.submod2.Type => submod2.Type
|
||||
if res.count('[') < 2 {
|
||||
mut parts := res.split('.')
|
||||
if parts.len > 1 {
|
||||
mut parts := res.split('.')
|
||||
if parts.len > 1 {
|
||||
if parts[..parts.len - 1].all(!it.contains('[')) {
|
||||
ind := parts.len - 2
|
||||
if t.is_fmt {
|
||||
// Rejoin the module parts for correct usage of aliases
|
||||
@ -1408,9 +1408,9 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
|
||||
}
|
||||
|
||||
res = parts[ind..].join('.')
|
||||
} else {
|
||||
res = parts[0]
|
||||
}
|
||||
} else {
|
||||
res = parts[0]
|
||||
}
|
||||
}
|
||||
return res
|
||||
|
@ -142,7 +142,7 @@ fn (mut g Gen) final_gen_str(typ StrType) {
|
||||
g.gen_str_for_fn_type(sym.info, styp, str_fn_name)
|
||||
}
|
||||
ast.Struct {
|
||||
g.gen_str_for_struct(sym.info, styp, str_fn_name)
|
||||
g.gen_str_for_struct(sym.info, styp, g.table.type_to_str(typ.typ), str_fn_name)
|
||||
}
|
||||
ast.Map {
|
||||
g.gen_str_for_map(sym.info, styp, str_fn_name)
|
||||
@ -151,10 +151,11 @@ fn (mut g Gen) final_gen_str(typ StrType) {
|
||||
g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
|
||||
}
|
||||
ast.SumType {
|
||||
g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name)
|
||||
g.gen_str_for_union_sum_type(sym.info, styp, g.table.type_to_str(typ.typ),
|
||||
str_fn_name)
|
||||
}
|
||||
ast.Interface {
|
||||
g.gen_str_for_interface(sym.info, styp, str_fn_name)
|
||||
g.gen_str_for_interface(sym.info, styp, g.table.type_to_str(typ.typ), str_fn_name)
|
||||
}
|
||||
ast.Chan {
|
||||
g.gen_str_for_chan(sym.info, styp, str_fn_name)
|
||||
@ -343,7 +344,7 @@ fn (mut g Gen) gen_str_for_enum(info ast.Enum, styp string, str_fn_name string)
|
||||
g.auto_str_funcs.writeln('}')
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_name string) {
|
||||
fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, typ_str string, str_fn_name string) {
|
||||
$if trace_autostr ? {
|
||||
eprintln('> gen_str_for_interface: ${info.types} | ${styp} | ${str_fn_name}')
|
||||
}
|
||||
@ -352,16 +353,7 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
|
||||
g.auto_str_funcs.writeln('static string ${str_fn_name}(${styp} x) { return indent_${str_fn_name}(x, 0); }')
|
||||
g.definitions.writeln('static string indent_${str_fn_name}(${styp} x, int indent_count); // auto')
|
||||
mut fn_builder := strings.new_builder(512)
|
||||
mut clean_interface_v_type_name := styp.replace('__', '.')
|
||||
if styp.ends_with('*') {
|
||||
clean_interface_v_type_name = '&' + clean_interface_v_type_name.replace('*', '')
|
||||
}
|
||||
if clean_interface_v_type_name.contains('_T_') {
|
||||
clean_interface_v_type_name =
|
||||
clean_interface_v_type_name.replace('Array_', '[]').replace('_T_', '[').replace('_', ', ') +
|
||||
']'
|
||||
}
|
||||
clean_interface_v_type_name = util.strip_main_name(clean_interface_v_type_name)
|
||||
clean_interface_v_type_name := util.strip_main_name(typ_str)
|
||||
fn_builder.writeln('static string indent_${str_fn_name}(${styp} x, int indent_count) { /* gen_str_for_interface */')
|
||||
for typ in info.types {
|
||||
sub_sym := g.table.sym(ast.mktyp(typ))
|
||||
@ -404,7 +396,7 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
|
||||
g.auto_fn_definitions << fn_builder.str()
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_name string) {
|
||||
fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, typ_str string, str_fn_name string) {
|
||||
$if trace_autostr ? {
|
||||
eprintln('> gen_str_for_union_sum_type: ${info.variants} | ${styp} | ${str_fn_name}')
|
||||
}
|
||||
@ -419,20 +411,11 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_
|
||||
variant_names := info.variants.map(util.strip_main_name(g.table.sym(it).name))
|
||||
clean_sum_type_v_type_name = '${variant_names.join('|')}'
|
||||
} else {
|
||||
clean_sum_type_v_type_name = styp.replace('__', '.')
|
||||
if styp.ends_with('*') {
|
||||
clean_sum_type_v_type_name = '&' + clean_sum_type_v_type_name.replace('*', '')
|
||||
}
|
||||
if clean_sum_type_v_type_name.contains('_T_') {
|
||||
clean_sum_type_v_type_name =
|
||||
clean_sum_type_v_type_name.replace('Array_', '[]').replace('_T_', '[').replace('_', ', ') +
|
||||
']'
|
||||
}
|
||||
clean_sum_type_v_type_name = util.strip_main_name(clean_sum_type_v_type_name)
|
||||
clean_sum_type_v_type_name = util.strip_main_name(typ_str)
|
||||
}
|
||||
fn_builder.writeln('\tswitch(x._typ) {')
|
||||
for typ in info.variants {
|
||||
typ_str := g.typ(typ)
|
||||
typ_name := g.typ(typ)
|
||||
mut func_name := g.get_str_fn(typ)
|
||||
sym := g.table.sym(typ)
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
@ -443,7 +426,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_
|
||||
|
||||
// str_intp
|
||||
if typ == ast.string_type {
|
||||
mut val := '${func_name}(${deref}(${typ_str}*)x._${sym.cname}'
|
||||
mut val := '${func_name}(${deref}(${typ_name}*)x._${sym.cname}'
|
||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||
val += ', indent_count'
|
||||
}
|
||||
@ -454,7 +437,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_
|
||||
}))'
|
||||
fn_builder.write_string('\t\tcase ${typ.idx()}: return ${res};\n')
|
||||
} else {
|
||||
mut val := '${func_name}(${deref}(${typ_str}*)x._${sym.cname}'
|
||||
mut val := '${func_name}(${deref}(${typ_name}*)x._${sym.cname}'
|
||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||
val += ', indent_count'
|
||||
}
|
||||
@ -827,7 +810,7 @@ fn (g &Gen) type_to_fmt(typ ast.Type) StrIntpType {
|
||||
return .si_i32
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name string) {
|
||||
fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, str_fn_name string) {
|
||||
$if trace_autostr ? {
|
||||
eprintln('> gen_str_for_struct: ${info.parent_type.debug()} | ${styp} | ${str_fn_name}')
|
||||
}
|
||||
@ -840,15 +823,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
|
||||
g.auto_fn_definitions << fn_builder.str()
|
||||
}
|
||||
fn_builder.writeln('static string indent_${str_fn_name}(${styp} it, int indent_count) {')
|
||||
mut clean_struct_v_type_name := styp.replace('__', '.')
|
||||
if clean_struct_v_type_name.contains('_T_') {
|
||||
// TODO: this is a bit hacky. styp shouldn't be even parsed with _T_
|
||||
// use something different than g.typ for styp
|
||||
clean_struct_v_type_name =
|
||||
clean_struct_v_type_name.replace('Array_', '[]').replace('_T_', '[').replace('_', ', ') +
|
||||
']'
|
||||
}
|
||||
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
|
||||
clean_struct_v_type_name := util.strip_main_name(typ_str)
|
||||
// generate ident / indent length = 4 spaces
|
||||
if info.fields.len == 0 {
|
||||
fn_builder.writeln('\treturn _SLIT("${clean_struct_v_type_name}{}");')
|
||||
|
80
vlib/v/tests/inout/printing_nested_generic_struct.out
Normal file
80
vlib/v/tests/inout/printing_nested_generic_struct.out
Normal file
@ -0,0 +1,80 @@
|
||||
{'one': 1, 'two': 2}
|
||||
[Tuple2[int, Tuple2[string, int]]{
|
||||
a: 0
|
||||
b: Tuple2[string, int]{
|
||||
a: 'one'
|
||||
b: 1
|
||||
}
|
||||
}, Tuple2[int, Tuple2[string, int]]{
|
||||
a: 1
|
||||
b: Tuple2[string, int]{
|
||||
a: 'two'
|
||||
b: 2
|
||||
}
|
||||
}]
|
||||
[Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{
|
||||
a: 0
|
||||
b: Tuple2[Tuple2[string, int], Tuple2[int, string]]{
|
||||
a: Tuple2[string, int]{
|
||||
a: 'one'
|
||||
b: 1
|
||||
}
|
||||
b: Tuple2[int, string]{
|
||||
a: 1
|
||||
b: 'one'
|
||||
}
|
||||
}
|
||||
}, Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{
|
||||
a: 1
|
||||
b: Tuple2[Tuple2[string, int], Tuple2[int, string]]{
|
||||
a: Tuple2[string, int]{
|
||||
a: 'two'
|
||||
b: 2
|
||||
}
|
||||
b: Tuple2[int, string]{
|
||||
a: 2
|
||||
b: 'two'
|
||||
}
|
||||
}
|
||||
}]
|
||||
{3: 'three', 4: 'four'}
|
||||
[Tuple2[int, Tuple2[int, string]]{
|
||||
a: 0
|
||||
b: Tuple2[int, string]{
|
||||
a: 3
|
||||
b: 'three'
|
||||
}
|
||||
}, Tuple2[int, Tuple2[int, string]]{
|
||||
a: 1
|
||||
b: Tuple2[int, string]{
|
||||
a: 4
|
||||
b: 'four'
|
||||
}
|
||||
}]
|
||||
[Tuple2[int, Tuple2[Tuple2[int, string], Tuple2[string, int]]]{
|
||||
a: 0
|
||||
b: Tuple2[Tuple2[int, string], Tuple2[string, int]]{
|
||||
a: Tuple2[int, string]{
|
||||
a: 3
|
||||
b: 'three'
|
||||
}
|
||||
b: Tuple2[string, int]{
|
||||
a: 'three'
|
||||
b: 3
|
||||
}
|
||||
}
|
||||
}, Tuple2[int, Tuple2[Tuple2[int, string], Tuple2[string, int]]]{
|
||||
a: 1
|
||||
b: Tuple2[Tuple2[int, string], Tuple2[string, int]]{
|
||||
a: Tuple2[int, string]{
|
||||
a: 4
|
||||
b: 'four'
|
||||
}
|
||||
b: Tuple2[string, int]{
|
||||
a: 'four'
|
||||
b: 4
|
||||
}
|
||||
}
|
||||
}]
|
||||
[]Tuple2[int, Tuple2[string, int]]
|
||||
[]Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]
|
55
vlib/v/tests/inout/printing_nested_generic_struct.vv
Normal file
55
vlib/v/tests/inout/printing_nested_generic_struct.vv
Normal file
@ -0,0 +1,55 @@
|
||||
struct Tuple2[A, B] {
|
||||
a A
|
||||
b B
|
||||
}
|
||||
|
||||
// map to array of Tuple2[int, Tuple2[key, value]] tuples
|
||||
fn map_to_array_int_kv[K, V](m map[K]V) []Tuple2[int, Tuple2[K, V]] {
|
||||
mut r := []Tuple2[int, Tuple2[K, V]]{cap: m.len}
|
||||
mut i := 0
|
||||
for k, v in m {
|
||||
r << Tuple2[int, Tuple2[K, V]]{i, Tuple2[K, V]{k, v}}
|
||||
i += 1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// map to array of Tuple2[int, Tuple2[Tuple2[key, value], Tuple2[value, key]]] tuples
|
||||
fn map_to_array_int_kv_vk[K, V](m map[K]V) []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]] {
|
||||
mut r := []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{cap: m.len}
|
||||
mut i := 0
|
||||
for k, v in m {
|
||||
r << Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{i, Tuple2[Tuple2[K, V], Tuple2[V, K]]{Tuple2[K, V]{k, v}, Tuple2[V, K]{v, k}}}
|
||||
i += 1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
fn main() {
|
||||
x := {
|
||||
'one': 1
|
||||
'two': 2
|
||||
}
|
||||
y := {
|
||||
3: 'three'
|
||||
4: 'four'
|
||||
}
|
||||
|
||||
println(x)
|
||||
rx1 := map_to_array_int_kv(x)
|
||||
println(rx1)
|
||||
rx2 := map_to_array_int_kv_vk(x)
|
||||
println(rx2)
|
||||
|
||||
println(y)
|
||||
ry1 := map_to_array_int_kv(y)
|
||||
println(ry1)
|
||||
ry2 := map_to_array_int_kv_vk(y)
|
||||
println(ry2)
|
||||
|
||||
// test typeof(X).name
|
||||
zx1 := []Tuple2[int, Tuple2[string, int]]{}
|
||||
println(typeof(zx1).name)
|
||||
zx2 := []Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{}
|
||||
println(typeof(zx2).name)
|
||||
}
|
@ -19,7 +19,7 @@ fn test_interpolation_of_v_structs_containing_c_structs() {
|
||||
}
|
||||
sxxx := xxx.str()
|
||||
assert sxxx == 'VStruct{
|
||||
a_c_struct: struct Abc{
|
||||
a_c_struct: C.Abc{
|
||||
char_pointer_field: &C"the string"
|
||||
}
|
||||
}'
|
||||
|
@ -458,7 +458,7 @@ fn test_c_struct_typedef() {
|
||||
}
|
||||
assert c.str() == r'CTypeDefStruct{
|
||||
mutex: &sync.Mutex{
|
||||
mutex: pthread_mutex_t{}
|
||||
mutex: C.pthread_mutex_t{}
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user