cgen: fix for `type FdfFn = fn(...) (x,y)`

pull/6299/head
Delyan Angelov 2020-10-11 09:53:35 +03:00
parent 77c29c6b6f
commit 604b28b1c5
3 changed files with 72 additions and 42 deletions

View File

@ -571,17 +571,30 @@ static inline void __${styp}_pushval($styp ch, $el_stype val) {
g.type_definitions.writeln('typedef map $styp;') g.type_definitions.writeln('typedef map $styp;')
} }
.function { .function {
info := typ.info as table.FnType g.write_fn_typesymbol_declaration(typ)
}
else {
continue
}
}
}
}
pub fn (mut g Gen) write_fn_typesymbol_declaration(sym table.TypeSymbol) {
info := sym.info as table.FnType
func := info.func func := info.func
sym := g.table.get_type_symbol(func.return_type) mut retsym := g.table.get_type_symbol(func.return_type)
is_multi := sym.kind == .multi_return is_multi := retsym.kind == .multi_return
is_fn_sig := func.name == '' is_fn_sig := func.name == ''
not_anon := !info.is_anon not_anon := !info.is_anon
if !info.has_decl && !is_multi && (not_anon || is_fn_sig) { 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 { fn_name := if func.language == .c {
util.no_dots(func.name) util.no_dots(func.name)
} else if info.is_anon { } else if info.is_anon {
typ.name sym.name
} else { } else {
c_name(func.name) c_name(func.name)
} }
@ -595,22 +608,13 @@ static inline void __${styp}_pushval($styp ch, $el_stype val) {
g.type_definitions.writeln(');') g.type_definitions.writeln(');')
} }
} }
else {
continue
}
}
}
}
pub fn (mut g Gen) write_multi_return_types() { pub fn (mut g Gen) write_multi_return_type_declaration(mut sym table.TypeSymbol) {
g.type_definitions.writeln('// multi return structs') if sym.is_written {
for typ in g.table.types { return
// sym := g.table.get_type_symbol(typ)
if typ.kind != .multi_return {
continue
} }
name := util.no_dots(typ.name) name := util.no_dots(sym.name)
info := typ.info as table.MultiReturn info := sym.info as table.MultiReturn
g.type_definitions.writeln('typedef struct {') g.type_definitions.writeln('typedef struct {')
// TODO copy pasta StructDecl // TODO copy pasta StructDecl
// for field in struct_info.fields { // for field in struct_info.fields {
@ -620,13 +624,22 @@ pub fn (mut g Gen) write_multi_return_types() {
} }
g.type_definitions.writeln('} $name;\n') g.type_definitions.writeln('} $name;\n')
// g.typedefs.writeln('typedef struct $name $name;') // 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() { pub fn (mut g Gen) write_variadic_types() {
if g.variadic_args.len > 0 { g.type_definitions.writeln('\n//BEGIN_variadic_structs')
g.type_definitions.writeln('// variadic structs')
}
for type_str, arg_len in g.variadic_args { for type_str, arg_len in g.variadic_args {
typ := table.Type(type_str.int()) typ := table.Type(type_str.int())
type_name := g.typ(typ) type_name := g.typ(typ)
@ -637,6 +650,7 @@ pub fn (mut g Gen) write_variadic_types() {
g.type_definitions.writeln('};\n') g.type_definitions.writeln('};\n')
g.typedefs.writeln('typedef struct $struct_name $struct_name;') 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) { pub fn (mut g Gen) write(s string) {

View File

@ -40,6 +40,7 @@ pub mut:
methods []Fn methods []Fn
mod string mod string
is_public bool 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 // max of 8

View File

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