diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 69dee6c44b..f69b0fc51f 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -571,29 +571,7 @@ static inline void __${styp}_pushval($styp ch, $el_stype val) { g.type_definitions.writeln('typedef map $styp;') } .function { - info := typ.info as table.FnType - func := info.func - sym := g.table.get_type_symbol(func.return_type) - is_multi := sym.kind == .multi_return - is_fn_sig := func.name == '' - not_anon := !info.is_anon - if !info.has_decl && !is_multi && (not_anon || is_fn_sig) { - fn_name := if func.language == .c { - util.no_dots(func.name) - } else if info.is_anon { - typ.name - } else { - c_name(func.name) - } - g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(') - for i, param in func.params { - g.type_definitions.write(g.typ(param.typ)) - if i < func.params.len - 1 { - g.type_definitions.write(',') - } - } - g.type_definitions.writeln(');') - } + g.write_fn_typesymbol_declaration(typ) } else { continue @@ -602,31 +580,66 @@ static inline void __${styp}_pushval($styp ch, $el_stype val) { } } -pub fn (mut g Gen) write_multi_return_types() { - g.type_definitions.writeln('// multi return structs') - for typ in g.table.types { - // sym := g.table.get_type_symbol(typ) - if typ.kind != .multi_return { - continue +pub fn (mut g Gen) write_fn_typesymbol_declaration(sym table.TypeSymbol) { + info := sym.info as table.FnType + func := info.func + mut retsym := g.table.get_type_symbol(func.return_type) + is_multi := retsym.kind == .multi_return + is_fn_sig := func.name == '' + not_anon := !info.is_anon + if is_multi { + g.write_multi_return_type_declaration(mut retsym) + } + if !info.has_decl && (not_anon || is_fn_sig) { + fn_name := if func.language == .c { + util.no_dots(func.name) + } else if info.is_anon { + sym.name + } else { + c_name(func.name) } - name := util.no_dots(typ.name) - info := typ.info as table.MultiReturn - g.type_definitions.writeln('typedef struct {') - // TODO copy pasta StructDecl - // for field in struct_info.fields { - for i, mr_typ in info.types { - type_name := g.typ(mr_typ) - g.type_definitions.writeln('\t$type_name arg$i;') + g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(') + for i, param in func.params { + g.type_definitions.write(g.typ(param.typ)) + if i < func.params.len - 1 { + g.type_definitions.write(',') + } } - g.type_definitions.writeln('} $name;\n') - // g.typedefs.writeln('typedef struct $name $name;') + g.type_definitions.writeln(');') } } -pub fn (mut g Gen) write_variadic_types() { - if g.variadic_args.len > 0 { - g.type_definitions.writeln('// variadic structs') +pub fn (mut g Gen) write_multi_return_type_declaration(mut sym table.TypeSymbol) { + if sym.is_written { + return } + name := util.no_dots(sym.name) + info := sym.info as table.MultiReturn + g.type_definitions.writeln('typedef struct {') + // TODO copy pasta StructDecl + // for field in struct_info.fields { + for i, mr_typ in info.types { + type_name := g.typ(mr_typ) + g.type_definitions.writeln('\t$type_name arg$i;') + } + g.type_definitions.writeln('} $name;\n') + // g.typedefs.writeln('typedef struct $name $name;') + sym.is_written = true +} + +pub fn (mut g Gen) write_multi_return_types() { + g.type_definitions.writeln('\n// BEGIN_multi_return_structs') + for idx in 0..g.table.types.len { + if g.table.types[idx].kind != .multi_return { + continue + } + g.write_multi_return_type_declaration(mut g.table.types[idx]) + } + g.type_definitions.writeln('// END_multi_return_structs\n') +} + +pub fn (mut g Gen) write_variadic_types() { + g.type_definitions.writeln('\n//BEGIN_variadic_structs') for type_str, arg_len in g.variadic_args { typ := table.Type(type_str.int()) type_name := g.typ(typ) @@ -637,6 +650,7 @@ pub fn (mut g Gen) write_variadic_types() { g.type_definitions.writeln('};\n') g.typedefs.writeln('typedef struct $struct_name $struct_name;') } + g.type_definitions.writeln('// END_variadic_structs\n') } pub fn (mut g Gen) write(s string) { diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index c146ca842a..74b2690819 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -40,6 +40,7 @@ pub mut: methods []Fn mod string is_public bool + is_written bool // set to true, when the backend definition for a symbol had been written, to avoid duplicates } // max of 8 diff --git a/vlib/v/tests/fn_type_aliases_test.v b/vlib/v/tests/fn_type_aliases_test.v new file mode 100644 index 0000000000..c45ebe59db --- /dev/null +++ b/vlib/v/tests/fn_type_aliases_test.v @@ -0,0 +1,15 @@ +type FdfFn = fn (x f64, params []f64) (f64, f64) + +fn abc(x f64, params []f64) (f64, f64) { + return x + params[0], x + params[1] +} + +fn printer(x f64, f FdfFn) string { + a, b := f(x, [10.0, 20.0]) + return 'a: ${a:5.2f} | b: ${b:5.2f}' +} + +fn test_function_with_multiple_return_values_can_be_type_aliased() { + res := printer(12.2, abc) + assert res == 'a: 22.20 | b: 32.20' +}