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
|
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)
|
||||||
|
@ -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,')
|
||||||
|
@ -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())
|
||||||
|
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