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' 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) { 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 str_method_expects_ptr != is_elem_ptr {
if 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 // custom methods management
has_custom_str := sym.has_method('str') sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
mut field_styp := g.typ(field.typ).replace('*', '') sftyp := g.typ(field.typ)
field_styp_fn_name := if has_custom_str { mut field_styp := sftyp.replace('*', '')
field_styp_fn_name := if sym_has_str_method {
'${field_styp}_str' '${field_styp}_str'
} else { } else {
g.get_str_fn(field.typ) 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)}=') 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 { if field.typ in ast.cptr_types {
func = '(voidptr) it.$field.name' func = '(voidptr) it.$field.name'
} else if field.typ.is_ptr() { } 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_builder.writeln('}')
} }
fn struct_auto_str_func1(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string) string { 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 {
has_custom_str, expects_ptr, _ := sym.str_method_info() deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type)
if sym.kind == .enum_ { 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) { } else if should_use_indent_func(sym.kind) {
mut obj := 'it.${c_name(field_name)}' obj := 'it.${c_name(field_name)}'
if field_type.is_ptr() && !expects_ptr {
obj = '*$obj'
}
if has_custom_str { 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] { } else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
if has_custom_str { 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 { } else if sym.kind == .function {
return '${fn_name}()' return '${fn_name}()'
} else { } else {
if sym.kind == .chan { 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)}' mut method_str := 'it.${c_name(field_name)}'
if sym.kind == .bool { 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_typedefs := map[string]bool{}
mut dump_fns := strings.new_builder(100) mut dump_fns := strings.new_builder(100)
for dump_type, cname in g.table.dumps { 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) 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' mut str_dumparg_type := '$cname$ptr_asterisk'
if dump_sym.kind == .function { if dump_sym.kind == .function {
fninfo := dump_sym.info as ast.FnType 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_typedefs['typedef $str_tdef;'] = true
} }
dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) 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) dump_fns)
{ {
continue continue
@ -52,8 +54,8 @@ fn (mut g Gen) dump_expr_definitions() {
if is_ptr { if is_ptr {
dump_fns.writeln('\teprint(${ctoslit('&')});') dump_fns.writeln('\teprint(${ctoslit('&')});')
} }
dump_fns.writeln('\teprintln(${to_string_fn_name}(${ptr_asterisk}x));') dump_fns.writeln('\teprintln(${to_string_fn_name}(${deref}dump_arg));')
dump_fns.writeln('\treturn x;') dump_fns.writeln('\treturn dump_arg;')
dump_fns.writeln('}') dump_fns.writeln('}')
} }
for tdef, _ in dump_typedefs { for tdef, _ in dump_typedefs {

View File

@ -20,3 +20,50 @@ fn test_dump_of_functions() {
assert foo == x assert foo == x
assert y == zoo 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
}