1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser, checker, cgen: implement generics anon fn (#15529)

This commit is contained in:
yuyi 2022-08-25 19:12:56 +08:00 committed by GitHub
parent 723b3d74ee
commit 40c0a8cbaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 3 deletions

View File

@ -122,6 +122,11 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
} }
continue continue
} }
if got_typ_sym.kind == .function && exp_typ_sym.kind == .function {
if (got_typ_sym.info as ast.FnType).is_anon {
continue
}
}
pos := node.exprs[expr_idxs[i]].pos() pos := node.exprs[expr_idxs[i]].pos()
c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument', c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument',
pos) pos)

View File

@ -445,14 +445,19 @@ fn closure_ctx(node ast.FnDecl) string {
fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) { fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
g.gen_anon_fn_decl(mut node) g.gen_anon_fn_decl(mut node)
mut fn_name := node.decl.name
if node.decl.generic_names.len > 0 {
fn_name = g.generic_fn_name(g.cur_concrete_types, fn_name, true)
}
if !node.decl.scope.has_inherited_vars() { if !node.decl.scope.has_inherited_vars() {
g.write(node.decl.name) g.write(fn_name)
return return
} }
ctx_struct := closure_ctx(node.decl) ctx_struct := closure_ctx(node.decl)
// it may be possible to optimize `memdup` out if the closure never leaves current scope // it may be possible to optimize `memdup` out if the closure never leaves current scope
// TODO in case of an assignment, this should only call "__closure_set_data" and "__closure_set_function" (and free the former data) // TODO in case of an assignment, this should only call "__closure_set_data" and "__closure_set_function" (and free the former data)
g.write('__closure_create($node.decl.name, ($ctx_struct*) memdup_uncollectable(&($ctx_struct){') g.write('__closure_create($fn_name, ($ctx_struct*) memdup_uncollectable(&($ctx_struct){')
g.indent++ g.indent++
for var in node.inherited_vars { for var in node.inherited_vars {
g.writeln('.$var.name = $var.name,') g.writeln('.$var.name = $var.name,')

View File

@ -677,7 +677,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
} }
p.scope.detached_from_parent = true p.scope.detached_from_parent = true
inherited_vars := if p.tok.kind == .lsbr { p.closure_vars() } else { []ast.Param{} } inherited_vars := if p.tok.kind == .lsbr { p.closure_vars() } else { []ast.Param{} }
// TODO generics _, generic_names := p.parse_generic_types()
args, _, is_variadic := p.fn_args() args, _, is_variadic := p.fn_args()
for arg in args { for arg in args {
if arg.name.len == 0 && p.table.sym(arg.typ).kind != .placeholder { if arg.name.len == 0 && p.table.sym(arg.typ).kind != .placeholder {
@ -759,6 +759,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
params: args params: args
is_variadic: is_variadic is_variadic: is_variadic
is_method: false is_method: false
generic_names: generic_names
is_anon: true is_anon: true
no_body: no_body no_body: no_body
pos: pos.extend(p.prev_tok.pos()) pos: pos.extend(p.prev_tok.pos())

View File

@ -0,0 +1,20 @@
fn setter<T>(mut m map[T]int) fn (T, int) {
return fn [mut m] <T>(x T, k int) {
m[x] = k
}
}
fn test_generics_closure_fn() {
mut m := {
f32(0.1): 1
}
f := setter(mut m)
f(0.2, 2)
println(m)
assert m == {
f32(0.1): 1
0.2: 2
}
}