parser: allow multi returns in high order fns
parent
236b34c009
commit
febd532c4a
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue