diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 35ec0fc56a..f6b27dc502 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -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 diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 424ee99b18..9161137890 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -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}{}");') diff --git a/vlib/v/tests/inout/printing_nested_generic_struct.out b/vlib/v/tests/inout/printing_nested_generic_struct.out new file mode 100644 index 0000000000..fa343f1159 --- /dev/null +++ b/vlib/v/tests/inout/printing_nested_generic_struct.out @@ -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]]] diff --git a/vlib/v/tests/inout/printing_nested_generic_struct.vv b/vlib/v/tests/inout/printing_nested_generic_struct.vv new file mode 100644 index 0000000000..79619fe22c --- /dev/null +++ b/vlib/v/tests/inout/printing_nested_generic_struct.vv @@ -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) +} diff --git a/vlib/v/tests/printing_c_structs/string_interpolation_test.v b/vlib/v/tests/printing_c_structs/string_interpolation_test.v index 2ea40d63d7..69d0712fba 100644 --- a/vlib/v/tests/printing_c_structs/string_interpolation_test.v +++ b/vlib/v/tests/printing_c_structs/string_interpolation_test.v @@ -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" } }' diff --git a/vlib/v/tests/str_gen_test.v b/vlib/v/tests/str_gen_test.v index dff13a12f6..21f49f87cd 100644 --- a/vlib/v/tests/str_gen_test.v +++ b/vlib/v/tests/str_gen_test.v @@ -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{} } }' }