diff --git a/compiler/fn.v b/compiler/fn.v index b91a80c6d4..a2072bd976 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -293,18 +293,6 @@ fn (p mut Parser) fn_decl() { p.fgen(' ') typ = p.get_type() } - // multiple returns - if typ.starts_with('_V_MulRet_') && p.first_pass() && !p.table.known_type(typ) { - p.table.register_type2(Type{ - cat: TypeCategory.struct_, - name: typ, - mod: p.mod - }) - for i, t in typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') { - p.table.add_field(typ, 'var_$i', t, false, '', .public) - } - p.cgen.typedefs << 'typedef struct $typ $typ;' - } // Translated C code and .vh can have empty functions (just definitions) is_fn_header := !is_c && !p.is_vh && (p.pref.translated || p.pref.is_test || p.is_vh) && @@ -733,9 +721,8 @@ fn (p mut Parser) fn_args(f mut Fn) { p.error('you must provide a type for vargs: eg `...string`. multiple types `...` are not supported yet.') } t := p.get_type() - vargs_struct := '_V_FnVargs_$f.name' // register varg struct, incase function is never called - p.fn_register_vargs_stuct(f, t, []string) + vargs_struct := p.fn_register_vargs_stuct(f, t, []string) p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n' typ = '...$t' } else { @@ -1018,7 +1005,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn { return f // TODO is return f right? } -fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) { +fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) string { vargs_struct := '_V_FnVargs_$f.name' varg_type := Type{ cat: TypeCategory.struct_, @@ -1032,6 +1019,7 @@ fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) { } p.table.add_field(vargs_struct, 'len', 'int', false, '', .public) p.table.add_field(vargs_struct, 'args[$values.len]', typ, false, '', .public) + return vargs_struct } fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) { @@ -1060,8 +1048,24 @@ fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) { if f.args.len > 1 { p.cgen.gen(',') } - p.cgen.gen('&(_V_FnVargs_$f.name){.len=$values.len,.args={'+values.join(',')+'}}') - p.fn_register_vargs_stuct(f, varg_def_type, values) + vargs_struct := p.fn_register_vargs_stuct(f, varg_def_type, values) + p.cgen.gen('&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}') + +} + +fn (p mut Parser) register_multi_return_stuct(types []string) string { + typ := '_V_MulRet_' + types.join('_V_').replace('*', '_PTR_') + if p.table.known_type(typ) { return typ } + p.table.register_type2(Type{ + cat: TypeCategory.struct_, + name: typ, + mod: p.mod + }) + for i, t in typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') { + p.table.add_field(typ, 'var_$i', t, false, '', .public) + } + p.cgen.typedefs << 'typedef struct $typ $typ;' + return typ } // "fn (int, string) int" diff --git a/compiler/parser.v b/compiler/parser.v index 0438e150a9..b154cde221 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -937,7 +937,8 @@ fn (p mut Parser) get_type() string { } p.check(.rpar) // p.inside_tuple = false - return '_V_MulRet_' + types.join('_V_').replace('*', '_PTR_') + typ = p.register_multi_return_stuct(types) + return typ } // fn type if p.tok == .func { diff --git a/compiler/tests/fn_test.v b/compiler/tests/fn_test.v index 8bcec835af..7125af85af 100644 --- a/compiler/tests/fn_test.v +++ b/compiler/tests/fn_test.v @@ -107,6 +107,14 @@ fn high_fn(f fn(int) int) { } +fn high_fn_array(f fn(a []int) []int) { + +} + +fn high_fn_multi_return(a int, b fn (c []int, d []string) ([]int, []string)) { + +} + fn test_fns() { // no asserts for now, just test function declarations above }