parser: allow multi returns in high order fns

pull/2272/head
joe-conigliaro 2019-10-10 04:55:36 +11:00 committed by Alexander Medvednikov
parent 236b34c009
commit febd532c4a
3 changed files with 31 additions and 18 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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
}