diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d33911a410..9afc131084 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -220,7 +220,8 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { if var.typ != 0 { vts := c.table.get_type_symbol(var.typ) if vts.kind == .function { - f = vts.info as table.Fn + info := vts.info as table.FnType + f = info.func found = true } } @@ -769,7 +770,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { } // Function object (not a call), e.g. `onclick(my_click)` if func := c.table.find_fn(name) { - fn_type := c.table.find_or_register_fn_type(func) + fn_type := table.new_type(c.table.find_or_register_fn_type(func, true)) ident.name = name ident.kind = .function ident.info = ast.IdentFn{ diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 848edcb1cb..3079b8a74f 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -110,8 +110,21 @@ pub fn (g mut Gen) write_typedef_types() { styp := typ.name.replace('.', '__') g.definitions.writeln('typedef map $styp;') } - // TODO: - .function {} + .function { + info := typ.info as table.FnType + func := info.func + if !info.has_decl && !info.is_anon { + fn_name := func.name.replace('.', '__') + g.definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(') + for i,arg in func.args { + g.definitions.write(g.typ(arg.typ)) + if i < func.args.len - 1 { + g.definitions.write(',') + } + } + g.definitions.writeln(');') + } + } else { continue } @@ -509,7 +522,8 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) { arg_type_name = 'varg_' + g.typ(arg.typ).replace('*', '_ptr') } if arg_type_sym.kind == .function { - func := arg_type_sym.info as table.Fn + info := arg_type_sym.info as table.FnType + func := info.func g.write('${g.typ(func.return_type)} (*$arg.name)(') g.definitions.write('${g.typ(func.return_type)} (*$arg.name)(') g.fn_args(func.args, func.is_variadic) diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 619d1abd9a..ce5b7f1df4 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -81,7 +81,7 @@ pub fn (p mut Parser) parse_fn_type(name string) table.Type { is_variadic: is_variadic return_type: return_type } - idx := p.table.find_or_register_fn_type(func) + idx := p.table.find_or_register_fn_type(func, false) return table.new_type(idx) } diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index 6005721d40..3c58c73873 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -7,7 +7,7 @@ import ( pub type Type int pub type TypeInfo = Array | ArrayFixed | Map | Struct | -MultiReturn | Alias | Enum | SumType | Fn +MultiReturn | Alias | Enum | SumType | FnType pub struct TypeSymbol { pub: @@ -214,6 +214,13 @@ mut: types []Type } +pub struct FnType { +pub: + is_anon bool + has_decl bool + func Fn +} + pub enum Kind { placeholder void diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index fbad26f24c..f0c77b60c5 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -388,12 +388,17 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int { return t.register_type_symbol(mr_type) } -pub fn (t mut Table) find_or_register_fn_type(f Fn) int { - name := if f.name.len > 0 { f.name } else { 'anon_$f.signature()' } +pub fn (t mut Table) find_or_register_fn_type(f Fn, has_decl bool) int { + is_anon := f.name.len == 0 + name := if is_anon { 'anon_fn_$f.signature()' } else { f.name } return t.register_type_symbol(TypeSymbol{ kind: .function name: name - info: f + info: FnType{ + is_anon: is_anon + has_decl: has_decl + func: f + } }) } @@ -485,9 +490,9 @@ pub fn (t &Table) check(got, expected Type) bool { } // fn type if got_type_sym.kind == .function && exp_type_sym.kind == .function { - got_fn := got_type_sym.info as Fn - exp_fn := exp_type_sym.info as Fn - if got_fn.signature() == exp_fn.signature() { + got_info := got_type_sym.info as FnType + exp_info := exp_type_sym.info as FnType + if got_info.func.signature() == exp_info.func.signature() { return true } }