diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 6e0db4c0fc..6a785d0a33 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -331,6 +331,9 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte { return `s` } } + if sym.kind == .function { + return `s` + } if ftyp in [table.string_type, table.bool_type] || sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_] || ftyp.has_flag(.optional) || diff --git a/vlib/v/gen/auto_str_methods.v b/vlib/v/gen/auto_str_methods.v index 5892cd5cb9..c46ce4bc34 100644 --- a/vlib/v/gen/auto_str_methods.v +++ b/vlib/v/gen/auto_str_methods.v @@ -40,6 +40,9 @@ fn (mut g Gen) gen_str_for_type(typ table.Type) string { table.Enum { g.gen_str_for_enum(sym.info, styp, str_fn_name) } + table.FnType { + g.gen_str_for_fn_type(sym.info, styp, str_fn_name) + } table.Struct { g.gen_str_for_struct(sym.info, styp, str_fn_name) } @@ -526,6 +529,26 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f g.auto_str_funcs.writeln('}') } +fn (mut g Gen) fn_decl_str(info table.FnType) string { + mut fn_str := 'fn (' + for i, arg in info.func.params { + if i > 0 { + fn_str += ', ' + } + fn_str += util.strip_main_name(g.table.get_type_name(arg.typ)) + } + fn_str += ')' + if info.func.return_type != table.void_type { + fn_str += ' ${util.strip_main_name(g.table.get_type_name(info.func.return_type))}' + } + return fn_str +} + +fn (mut g Gen) gen_str_for_fn_type(info table.FnType, styp string, str_fn_name string) { + g.type_definitions.writeln('static string ${str_fn_name}(); // auto') + g.auto_str_funcs.writeln('static string ${str_fn_name}() { return _SLIT("${g.fn_decl_str(info)}");}') +} + [inline] fn styp_to_str_fn_name(styp string) string { return styp.replace_each(['*', '', '.', '__']) + '_str' diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 098a2e86be..d30a2b6b9b 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2741,19 +2741,7 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) { g.write('_SLIT("[$fixed_info.size]${util.strip_main_name(typ_name)}")') } else if sym.kind == .function { info := sym.info as table.FnType - fn_info := info.func - mut repr := 'fn (' - for i, arg in fn_info.params { - if i > 0 { - repr += ', ' - } - repr += util.strip_main_name(g.table.get_type_name(arg.typ)) - } - repr += ')' - if fn_info.return_type != table.void_type { - repr += ' ${util.strip_main_name(g.table.get_type_name(fn_info.return_type))}' - } - g.write('_SLIT("$repr")') + g.write('_SLIT("${g.fn_decl_str(info)}")') } else if node.expr_type.has_flag(.variadic) { g.write('_SLIT("...${util.strip_main_name(sym.name)}")') } else { diff --git a/vlib/v/tests/string_interpolation_function_test.v b/vlib/v/tests/string_interpolation_function_test.v new file mode 100644 index 0000000000..b563fdd60e --- /dev/null +++ b/vlib/v/tests/string_interpolation_function_test.v @@ -0,0 +1,12 @@ +fn show(a string) string { + return a +} + +fn test_function_interpolation() { + f := fn()(string, bool) {return 'aaa', true} + println(f) + assert '$f' == 'fn () (string, bool)' + + println(show) + assert '$show' == 'fn (string) string' +}