checker: allow for each(a, |x| println(x)), i.e. using lambda expressions, when expecting fn (x int)

This commit is contained in:
Delyan Angelov 2023-09-27 11:49:12 +03:00
parent b81a5325ef
commit e115d4461c
No known key found for this signature in database
GPG key ID: 66886C0F12D595ED
2 changed files with 55 additions and 6 deletions

View file

@ -33,3 +33,17 @@ fn test_all() {
assert !a.all(|x| x > 4)
assert a.all(|x| x < 40)
}
fn each(a []int, cb fn (x int)) {
for x in a {
cb(x)
}
}
fn test_using_lambda_expr_that_does_not_return_as_cb() {
each(a, fn (x int) {
println(x)
})
each(a, |x| println(x))
each(a, |x| dump(x))
}

View file

@ -24,11 +24,15 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
return ast.void_type
}
mut params := []ast.Param{}
mut generic_types := map[ast.Type]bool{}
for idx, mut x in node.params {
eparam := exp_sym.info.func.params[idx]
eparam_type := eparam.typ
eparam_auto_deref := eparam.typ.is_ptr()
c.lambda_expr_fix_type_of_param(mut node, mut x, eparam_type)
if eparam_type.has_flag(.generic) {
generic_types[eparam_type] = true
}
params << ast.Param{
pos: x.pos
name: x.name
@ -37,16 +41,42 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
is_auto_rec: eparam_auto_deref
}
}
/////
is_variadic := false
return_type := exp_sym.info.func.return_type
return_type_pos := node.pos
if return_type.has_flag(.generic) {
generic_types[return_type] = true
}
mut generic_names := []string{}
for t, _ in generic_types {
gtnames := c.table.generic_type_names(t)
for x in gtnames {
if x !in generic_names {
generic_names << x
}
}
}
// dump(generic_types)
// dump(generic_names)
mut stmts := []ast.Stmt{}
mut return_stmt := ast.Return{
mut has_return := false
if return_type == ast.void_type {
stmts << ast.ExprStmt{
pos: node.pos
expr: node.expr
is_expr: false
typ: return_type
}
} else {
stmts << ast.Return{
pos: node.pos
exprs: [node.expr]
}
stmts << return_stmt
has_return = true
}
mut func := ast.Fn{
params: params
@ -64,6 +94,7 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
short_name: ''
mod: c.file.mod.name
stmts: stmts
has_return: has_return
return_type: return_type
return_type_pos: return_type_pos
params: params
@ -74,9 +105,13 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
pos: node.pos.extend(node.pos_end)
file: c.file.path
scope: node.scope.parent
generic_names: generic_names
}
typ: typ
}
if node.func.decl.generic_names.len > 0 {
c.table.register_fn_generic_types(node.func.decl.fkey())
}
c.anon_fn(mut node.func)
}
node.is_checked = true