parent
844662e0d6
commit
d236d6a473
|
@ -724,14 +724,17 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_
|
|||
fn (mut g Gen) fn_decl_str(info ast.FnType) string {
|
||||
mut fn_str := 'fn ('
|
||||
for i, arg in info.func.params {
|
||||
if arg.is_mut {
|
||||
fn_str += 'mut '
|
||||
}
|
||||
if i > 0 {
|
||||
fn_str += ', '
|
||||
}
|
||||
fn_str += util.strip_main_name(g.table.get_type_name(arg.typ))
|
||||
fn_str += util.strip_main_name(g.table.get_type_name(g.unwrap_generic(arg.typ)))
|
||||
}
|
||||
fn_str += ')'
|
||||
if info.func.return_type != ast.void_type {
|
||||
fn_str += ' ${util.strip_main_name(g.table.get_type_name(info.func.return_type))}'
|
||||
fn_str += ' ${util.strip_main_name(g.table.get_type_name(g.unwrap_generic(info.func.return_type)))}'
|
||||
}
|
||||
return fn_str
|
||||
}
|
||||
|
|
|
@ -3229,12 +3229,18 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
}
|
||||
|
||||
// T.name, typeof(expr).name
|
||||
fn (mut g Gen) type_name(type_ ast.Type) {
|
||||
mut typ := type_
|
||||
if typ.has_flag(.generic) {
|
||||
typ = g.cur_concrete_types[0]
|
||||
fn (mut g Gen) type_name(typ ast.Type) {
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
mut s := ''
|
||||
if sym.kind == .function {
|
||||
if typ.is_ptr() {
|
||||
s = '&' + g.fn_decl_str(sym.info as ast.FnType)
|
||||
} else {
|
||||
s = g.fn_decl_str(sym.info as ast.FnType)
|
||||
}
|
||||
} else {
|
||||
s = g.table.type_to_str(g.unwrap_generic(typ))
|
||||
}
|
||||
s := g.table.type_to_str(typ)
|
||||
g.write('_SLIT("${util.strip_main_name(s)}")')
|
||||
}
|
||||
|
||||
|
|
|
@ -703,6 +703,8 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
|
|||
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn, .lsbr]
|
||||
|| (p.peek_tok.kind == .comma && p.table.known_type(argname))
|
||||
|| p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar
|
||||
|| (p.tok.kind == .key_mut && (p.peek_token(2).kind == .comma
|
||||
|| p.peek_token(2).kind == .rpar))
|
||||
// TODO copy pasta, merge 2 branches
|
||||
if types_only {
|
||||
mut arg_no := 1
|
||||
|
|
|
@ -193,11 +193,21 @@ pub fn (mut p Parser) parse_multi_return_type() ast.Type {
|
|||
pub fn (mut p Parser) parse_fn_type(name string) ast.Type {
|
||||
// p.warn('parse fn')
|
||||
p.check(.key_fn)
|
||||
mut has_generic := false
|
||||
line_nr := p.tok.line_nr
|
||||
args, _, is_variadic := p.fn_args()
|
||||
for arg in args {
|
||||
if arg.typ.has_flag(.generic) {
|
||||
has_generic = true
|
||||
break
|
||||
}
|
||||
}
|
||||
mut return_type := ast.void_type
|
||||
if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() {
|
||||
return_type = p.parse_type()
|
||||
if return_type.has_flag(.generic) {
|
||||
has_generic = true
|
||||
}
|
||||
}
|
||||
func := ast.Fn{
|
||||
name: name
|
||||
|
@ -209,6 +219,9 @@ pub fn (mut p Parser) parse_fn_type(name string) ast.Type {
|
|||
// because typedefs get generated after the map struct is generated
|
||||
has_decl := p.builtin_mod && name.starts_with('Map') && name.ends_with('Fn')
|
||||
idx := p.table.find_or_register_fn_type(p.mod, func, false, has_decl)
|
||||
if has_generic {
|
||||
return ast.new_type(idx).set_flag(.generic)
|
||||
}
|
||||
return ast.new_type(idx)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
struct Client {}
|
||||
|
||||
fn add_handler<T>(handler fn (mut Client, T)) string {
|
||||
return typeof(handler).name
|
||||
}
|
||||
|
||||
fn on_message(mut client Client, event string) {
|
||||
println(event)
|
||||
}
|
||||
|
||||
fn test_generics_fn_typeof_name() {
|
||||
ret := add_handler<string>(on_message)
|
||||
println(ret)
|
||||
assert ret == 'fn (mut Client, string)'
|
||||
}
|
Loading…
Reference in New Issue