cgen: fix `dump(x)` with `fn (x &Type) str() string {`

pull/12529/head
Delyan Angelov 2021-11-20 13:12:03 +02:00
parent 24ffc1ffb2
commit 90ba856107
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 71 additions and 22 deletions

View File

@ -506,6 +506,7 @@ fn styp_to_str_fn_name(styp string) string {
return styp.replace_each(['*', '', '.', '__', ' ', '__']) + '_str'
}
// deref_kind returns deref, deref_label
fn deref_kind(str_method_expects_ptr bool, is_elem_ptr bool, typ ast.Type) (string, string) {
if str_method_expects_ptr != is_elem_ptr {
if is_elem_ptr {
@ -823,9 +824,10 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
}
// custom methods management
has_custom_str := sym.has_method('str')
mut field_styp := g.typ(field.typ).replace('*', '')
field_styp_fn_name := if has_custom_str {
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
sftyp := g.typ(field.typ)
mut field_styp := sftyp.replace('*', '')
field_styp_fn_name := if sym_has_str_method {
'${field_styp}_str'
} else {
g.get_str_fn(field.typ)
@ -839,7 +841,8 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
fn_builder.write_string('{_SLIT("$quote_str"), $g_fmt, {.${data_str(base_fmt)}=')
}
mut func := struct_auto_str_func1(sym, field.typ, field_styp_fn_name, field.name)
mut func := struct_auto_str_func1(sym, field.typ, field_styp_fn_name, field.name,
sym_has_str_method, str_method_expects_ptr)
if field.typ in ast.cptr_types {
func = '(voidptr) it.$field.name'
} else if field.typ.is_ptr() {
@ -875,29 +878,26 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri
fn_builder.writeln('}')
}
fn struct_auto_str_func1(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string) string {
has_custom_str, expects_ptr, _ := sym.str_method_info()
fn struct_auto_str_func1(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string, has_custom_str bool, expects_ptr bool) string {
deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type)
if sym.kind == .enum_ {
return '${fn_name}(it.${c_name(field_name)})'
return '${fn_name}(${deref}it.${c_name(field_name)})'
} else if should_use_indent_func(sym.kind) {
mut obj := 'it.${c_name(field_name)}'
if field_type.is_ptr() && !expects_ptr {
obj = '*$obj'
}
obj := 'it.${c_name(field_name)}'
if has_custom_str {
return '${fn_name}($obj)'
return '${fn_name}($deref$obj)'
}
return 'indent_${fn_name}($obj, indent_count + 1)'
return 'indent_${fn_name}($deref$obj, indent_count + 1)'
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
if has_custom_str {
return '${fn_name}(it.${c_name(field_name)})'
return '${fn_name}(${deref}it.${c_name(field_name)})'
}
return 'indent_${fn_name}(it.${c_name(field_name)}, indent_count + 1)'
return 'indent_${fn_name}(${deref}it.${c_name(field_name)}, indent_count + 1)'
} else if sym.kind == .function {
return '${fn_name}()'
} else {
if sym.kind == .chan {
return '${fn_name}(it.${c_name(field_name)})'
return '${fn_name}(${deref}it.${c_name(field_name)})'
}
mut method_str := 'it.${c_name(field_name)}'
if sym.kind == .bool {

View File

@ -21,10 +21,12 @@ fn (mut g Gen) dump_expr_definitions() {
mut dump_typedefs := map[string]bool{}
mut dump_fns := strings.new_builder(100)
for dump_type, cname in g.table.dumps {
to_string_fn_name := g.get_str_fn(dump_type)
is_ptr := ast.Type(dump_type).is_ptr()
ptr_asterisk := if is_ptr { '*' } else { '' }
dump_sym := g.table.get_type_symbol(dump_type)
_, str_method_expects_ptr, _ := dump_sym.str_method_info()
is_ptr := ast.Type(dump_type).is_ptr()
deref, _ := deref_kind(str_method_expects_ptr, is_ptr, dump_type)
to_string_fn_name := g.get_str_fn(dump_type)
ptr_asterisk := if is_ptr { '*' } else { '' }
mut str_dumparg_type := '$cname$ptr_asterisk'
if dump_sym.kind == .function {
fninfo := dump_sym.info as ast.FnType
@ -36,7 +38,7 @@ fn (mut g Gen) dump_expr_definitions() {
dump_typedefs['typedef $str_tdef;'] = true
}
dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' })
if g.writeln_fn_header('$str_dumparg_type ${dump_fn_name}(string fpath, int line, string sexpr, $str_dumparg_type x)', mut
if g.writeln_fn_header('$str_dumparg_type ${dump_fn_name}(string fpath, int line, string sexpr, $str_dumparg_type dump_arg)', mut
dump_fns)
{
continue
@ -52,8 +54,8 @@ fn (mut g Gen) dump_expr_definitions() {
if is_ptr {
dump_fns.writeln('\teprint(${ctoslit('&')});')
}
dump_fns.writeln('\teprintln(${to_string_fn_name}(${ptr_asterisk}x));')
dump_fns.writeln('\treturn x;')
dump_fns.writeln('\teprintln(${to_string_fn_name}(${deref}dump_arg));')
dump_fns.writeln('\treturn dump_arg;')
dump_fns.writeln('}')
}
for tdef, _ in dump_typedefs {

View File

@ -20,3 +20,50 @@ fn test_dump_of_functions() {
assert foo == x
assert y == zoo
}
//
struct StructWithStrMethodTakingReference {
x int
}
pub fn (t &StructWithStrMethodTakingReference) str() string {
return 'StructWithStrMethodTakingReference{x: $t.x}'
}
fn test_dump_of_type_that_has_custom_str_method_with_reference_parameter() {
s := StructWithStrMethodTakingReference{123}
assert dump(s).x == 123
ps := &StructWithStrMethodTakingReference{456}
assert dump(ps).x == 456
}
//
struct StructWithNormalStrMethod {
x int
}
pub fn (t StructWithNormalStrMethod) str() string {
return 'StructWithNormalStrMethod{x: $t.x}'
}
fn test_dump_of_type_that_has_normal_custom_str_method() {
s := StructWithNormalStrMethod{123}
assert dump(s).x == 123
ps := &StructWithNormalStrMethod{456}
assert dump(ps).x == 456
}
//
struct StructWithoutStrMethod {
x int
}
fn test_dump_of_type_that_has_no_custom_str_method() {
s := StructWithoutStrMethod{123}
assert dump(s).x == 123
ps := &StructWithoutStrMethod{456}
assert dump(ps).x == 456
}