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:
parent
723b3d74ee
commit
40c0a8cbaf
@ -122,6 +122,11 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
|
||||
}
|
||||
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()
|
||||
c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument',
|
||||
pos)
|
||||
|
@ -445,14 +445,19 @@ fn closure_ctx(node ast.FnDecl) string {
|
||||
|
||||
fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
|
||||
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() {
|
||||
g.write(node.decl.name)
|
||||
g.write(fn_name)
|
||||
return
|
||||
}
|
||||
ctx_struct := closure_ctx(node.decl)
|
||||
// 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)
|
||||
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++
|
||||
for var in node.inherited_vars {
|
||||
g.writeln('.$var.name = $var.name,')
|
||||
|
@ -677,7 +677,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||
}
|
||||
p.scope.detached_from_parent = true
|
||||
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()
|
||||
for arg in args {
|
||||
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
|
||||
is_variadic: is_variadic
|
||||
is_method: false
|
||||
generic_names: generic_names
|
||||
is_anon: true
|
||||
no_body: no_body
|
||||
pos: pos.extend(p.prev_tok.pos())
|
||||
|
20
vlib/v/tests/generics_closure_fn_test.v
Normal file
20
vlib/v/tests/generics_closure_fn_test.v
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user