From ad41cd5c6f35dd236751e26b07a83a9af66660cd Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 23 Jul 2021 10:50:50 +0300 Subject: [PATCH] cgen: fix `dump(fn_name)` (closes #10912) --- vlib/v/gen/c/dumpexpr.v | 78 ++++++++++++++++++++---------------- vlib/v/tests/dump_fns_test.v | 22 ++++++++++ 2 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 vlib/v/tests/dump_fns_test.v diff --git a/vlib/v/gen/c/dumpexpr.v b/vlib/v/gen/c/dumpexpr.v index 9813739a8b..fcb6bbd750 100644 --- a/vlib/v/gen/c/dumpexpr.v +++ b/vlib/v/gen/c/dumpexpr.v @@ -1,6 +1,7 @@ module c import v.ast +import strings fn (mut g Gen) dump_expr(node ast.DumpExpr) { sexpr := ctoslit(node.expr.str()) @@ -17,48 +18,55 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) { } fn (mut g Gen) dump_expr_definitions() { - if g.pref.build_mode == .build_module { - for dump_type, cname in g.table.dumps { - is_ptr := ast.Type(dump_type).is_ptr() - ptr_suffix := if is_ptr { '*' } else { '' } - dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) - g.writeln_fn_header('$cname$ptr_suffix ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_suffix x)') + 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.gen_str_for_type(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) + mut str_dumparg_type := '$cname$ptr_asterisk' + if dump_sym.kind == .function { + fninfo := dump_sym.info as ast.FnType + str_dumparg_type = 'DumpFNType_$cname' + tdef_pos := g.out.len + g.write_fn_ptr_decl(&fninfo, str_dumparg_type) + str_tdef := g.out.after(tdef_pos) + g.out.go_back(str_tdef.len) + dump_typedefs['typedef $str_tdef;'] = true } - } else { - for dump_type, cname in g.table.dumps { - to_string_fn_name := g.gen_str_for_type(dump_type) - is_ptr := ast.Type(dump_type).is_ptr() - ptr_astarisk := if is_ptr { '*' } else { '' } - dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) - if g.writeln_fn_header('$cname$ptr_astarisk ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_astarisk x)') { - continue - } - g.definitions.writeln('\teprint(${ctoslit('[')});') - g.definitions.writeln('\teprint(fpath);') - g.definitions.writeln('\teprint(${ctoslit(':')});') - g.definitions.writeln('\teprint(int_str(line));') - g.definitions.writeln('\teprint(${ctoslit('] ')});') - - // g.definitions.writeln('\t/* dump_type: $dump_type | to_string_fn_name: $to_string_fn_name | is_ptr: $is_ptr | ptr_astarisk: $ptr_astarisk | dump_fn_name: $dump_fn_name | cname: $cname */') - g.definitions.writeln('\teprint(sexpr);') - g.definitions.writeln('\teprint(${ctoslit(': ')});') - - if is_ptr { - g.definitions.writeln('\teprint(${ctoslit('&')});') - } - g.definitions.writeln('\teprintln(${to_string_fn_name}(${ptr_astarisk}x));') - - g.definitions.writeln('\treturn x;') - g.definitions.writeln('}') + 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 + dump_fns) + { + continue } + dump_fns.writeln('\teprint(${ctoslit('[')});') + dump_fns.writeln('\teprint(fpath);') + dump_fns.writeln('\teprint(${ctoslit(':')});') + dump_fns.writeln('\teprint(int_str(line));') + dump_fns.writeln('\teprint(${ctoslit('] ')});') + // dump_fns.writeln('\t/* dump_type: $dump_type | to_string_fn_name: $to_string_fn_name | is_ptr: $is_ptr | ptr_asterisk: $ptr_asterisk | dump_fn_name: $dump_fn_name | cnam: $cname */') + dump_fns.writeln('\teprint(sexpr);') + dump_fns.writeln('\teprint(${ctoslit(': ')});') + 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('}') } + for tdef, _ in dump_typedefs { + g.definitions.writeln(tdef) + } + g.definitions.writeln(dump_fns.str()) } -fn (mut g Gen) writeln_fn_header(s string) bool { +fn (mut g Gen) writeln_fn_header(s string, mut sb strings.Builder) bool { if g.pref.build_mode == .build_module { - g.definitions.writeln('$s;') + sb.writeln('$s;') return true } - g.definitions.writeln('$s {') + sb.writeln('$s {') return false } diff --git a/vlib/v/tests/dump_fns_test.v b/vlib/v/tests/dump_fns_test.v new file mode 100644 index 0000000000..c56b1eff58 --- /dev/null +++ b/vlib/v/tests/dump_fns_test.v @@ -0,0 +1,22 @@ +fn foo() int { + return 1 +} + +fn zoo() int { + return 123 +} + +fn test_dump_of_functions() { + x := dump(foo) + y := dump(zoo) + dump(foo()) + dump(zoo()) + dump(x) + dump(y) + dump(x()) + dump(y()) + assert voidptr(x) != 0 + assert voidptr(y) != 0 + assert foo == x + assert y == zoo +}