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:
@@ -1395,9 +1395,9 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
|
|||||||
}
|
}
|
||||||
// types defined by the user
|
// types defined by the user
|
||||||
// mod.submod.submod2.Type => submod2.Type
|
// mod.submod.submod2.Type => submod2.Type
|
||||||
if res.count('[') < 2 {
|
mut parts := res.split('.')
|
||||||
mut parts := res.split('.')
|
if parts.len > 1 {
|
||||||
if parts.len > 1 {
|
if parts[..parts.len - 1].all(!it.contains('[')) {
|
||||||
ind := parts.len - 2
|
ind := parts.len - 2
|
||||||
if t.is_fmt {
|
if t.is_fmt {
|
||||||
// Rejoin the module parts for correct usage of aliases
|
// 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('.')
|
res = parts[ind..].join('.')
|
||||||
} else {
|
|
||||||
res = parts[0]
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res = parts[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res
|
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)
|
g.gen_str_for_fn_type(sym.info, styp, str_fn_name)
|
||||||
}
|
}
|
||||||
ast.Struct {
|
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 {
|
ast.Map {
|
||||||
g.gen_str_for_map(sym.info, styp, str_fn_name)
|
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)
|
g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
|
||||||
}
|
}
|
||||||
ast.SumType {
|
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 {
|
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 {
|
ast.Chan {
|
||||||
g.gen_str_for_chan(sym.info, styp, str_fn_name)
|
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('}')
|
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 ? {
|
$if trace_autostr ? {
|
||||||
eprintln('> gen_str_for_interface: ${info.types} | ${styp} | ${str_fn_name}')
|
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.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')
|
g.definitions.writeln('static string indent_${str_fn_name}(${styp} x, int indent_count); // auto')
|
||||||
mut fn_builder := strings.new_builder(512)
|
mut fn_builder := strings.new_builder(512)
|
||||||
mut clean_interface_v_type_name := styp.replace('__', '.')
|
clean_interface_v_type_name := util.strip_main_name(typ_str)
|
||||||
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)
|
|
||||||
fn_builder.writeln('static string indent_${str_fn_name}(${styp} x, int indent_count) { /* gen_str_for_interface */')
|
fn_builder.writeln('static string indent_${str_fn_name}(${styp} x, int indent_count) { /* gen_str_for_interface */')
|
||||||
for typ in info.types {
|
for typ in info.types {
|
||||||
sub_sym := g.table.sym(ast.mktyp(typ))
|
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()
|
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 ? {
|
$if trace_autostr ? {
|
||||||
eprintln('> gen_str_for_union_sum_type: ${info.variants} | ${styp} | ${str_fn_name}')
|
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))
|
variant_names := info.variants.map(util.strip_main_name(g.table.sym(it).name))
|
||||||
clean_sum_type_v_type_name = '${variant_names.join('|')}'
|
clean_sum_type_v_type_name = '${variant_names.join('|')}'
|
||||||
} else {
|
} else {
|
||||||
clean_sum_type_v_type_name = styp.replace('__', '.')
|
clean_sum_type_v_type_name = util.strip_main_name(typ_str)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\tswitch(x._typ) {')
|
fn_builder.writeln('\tswitch(x._typ) {')
|
||||||
for typ in info.variants {
|
for typ in info.variants {
|
||||||
typ_str := g.typ(typ)
|
typ_name := g.typ(typ)
|
||||||
mut func_name := g.get_str_fn(typ)
|
mut func_name := g.get_str_fn(typ)
|
||||||
sym := g.table.sym(typ)
|
sym := g.table.sym(typ)
|
||||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
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
|
// str_intp
|
||||||
if typ == ast.string_type {
|
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 {
|
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
val += ', indent_count'
|
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')
|
fn_builder.write_string('\t\tcase ${typ.idx()}: return ${res};\n')
|
||||||
} else {
|
} 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 {
|
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
val += ', indent_count'
|
val += ', indent_count'
|
||||||
}
|
}
|
||||||
@@ -827,7 +810,7 @@ fn (g &Gen) type_to_fmt(typ ast.Type) StrIntpType {
|
|||||||
return .si_i32
|
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 ? {
|
$if trace_autostr ? {
|
||||||
eprintln('> gen_str_for_struct: ${info.parent_type.debug()} | ${styp} | ${str_fn_name}')
|
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()
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
}
|
}
|
||||||
fn_builder.writeln('static string indent_${str_fn_name}(${styp} it, int indent_count) {')
|
fn_builder.writeln('static string indent_${str_fn_name}(${styp} it, int indent_count) {')
|
||||||
mut clean_struct_v_type_name := styp.replace('__', '.')
|
clean_struct_v_type_name := util.strip_main_name(typ_str)
|
||||||
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)
|
|
||||||
// generate ident / indent length = 4 spaces
|
// generate ident / indent length = 4 spaces
|
||||||
if info.fields.len == 0 {
|
if info.fields.len == 0 {
|
||||||
fn_builder.writeln('\treturn _SLIT("${clean_struct_v_type_name}{}");')
|
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()
|
sxxx := xxx.str()
|
||||||
assert sxxx == 'VStruct{
|
assert sxxx == 'VStruct{
|
||||||
a_c_struct: struct Abc{
|
a_c_struct: C.Abc{
|
||||||
char_pointer_field: &C"the string"
|
char_pointer_field: &C"the string"
|
||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
|
|||||||
@@ -458,7 +458,7 @@ fn test_c_struct_typedef() {
|
|||||||
}
|
}
|
||||||
assert c.str() == r'CTypeDefStruct{
|
assert c.str() == r'CTypeDefStruct{
|
||||||
mutex: &sync.Mutex{
|
mutex: &sync.Mutex{
|
||||||
mutex: pthread_mutex_t{}
|
mutex: C.pthread_mutex_t{}
|
||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user