checker: check array.map/filter fn or anon_fn
parent
8f3f27f286
commit
a66753871d
|
@ -754,6 +754,37 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
|||
return c.call_fn(call_expr)
|
||||
}
|
||||
|
||||
fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_expr ast.CallExpr) {
|
||||
elem_sym := c.table.get_type_symbol(elem_typ)
|
||||
match call_expr.args[0].expr {
|
||||
ast.AnonFn {
|
||||
if it.decl.args.len > 1 {
|
||||
c.error('function needs exactly 1 argument', call_expr.pos)
|
||||
} else if is_map && (it.decl.return_type != elem_typ || it.decl.args[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`', call_expr.pos)
|
||||
} else if !is_map && (it.decl.return_type != table.bool_type || it.decl.args[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`', call_expr.pos)
|
||||
}
|
||||
}
|
||||
ast.Ident {
|
||||
if it.kind == .function {
|
||||
func := c.table.find_fn(it.name) or {
|
||||
c.error('$it.name is not exist', it.pos)
|
||||
return
|
||||
}
|
||||
if func.args.len > 1 {
|
||||
c.error('function needs exactly 1 argument', call_expr.pos)
|
||||
} else if is_map && (func.return_type != elem_typ || func.args[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`', call_expr.pos)
|
||||
} else if !is_map && (func.return_type != table.bool_type || func.args[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`', call_expr.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
left_type := c.expr(call_expr.left)
|
||||
is_generic := left_type == table.t_type
|
||||
|
@ -764,10 +795,12 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
// FIXME: Argument count != 1 will break these
|
||||
if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',
|
||||
'map', 'slice'] {
|
||||
mut elem_typ := table.void_type
|
||||
if method_name in ['filter', 'map'] {
|
||||
array_info := left_type_sym.info as table.Array
|
||||
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||
scope.update_var_type('it', array_info.elem_type)
|
||||
elem_typ = array_info.elem_type
|
||||
}
|
||||
// map/filter are supposed to have 1 arg only
|
||||
mut arg_type := left_type
|
||||
|
@ -777,6 +810,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
call_expr.return_type = left_type
|
||||
call_expr.receiver_type = left_type
|
||||
if method_name == 'map' {
|
||||
// check fn
|
||||
c.check_map_and_filter(true, elem_typ, call_expr)
|
||||
arg_sym := c.table.get_type_symbol(arg_type)
|
||||
// FIXME: match expr failed for now
|
||||
mut ret_type := 0
|
||||
|
@ -785,6 +820,9 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
else { ret_type = arg_type }
|
||||
}
|
||||
call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod)
|
||||
} else if method_name == 'filter' {
|
||||
// check fn
|
||||
c.check_map_and_filter(false, elem_typ, call_expr)
|
||||
} else if method_name == 'clone' {
|
||||
// need to return `array_xxx` instead of `array`
|
||||
// in ['clone', 'str'] {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/array_filter_anon_fn_err_a.v:2:23: error: function needs exactly 1 argument
|
||||
1 | fn main() {
|
||||
2 | a := [1,2,3,4].filter(fn(a int, b int) bool { return a > 0 })
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
3 | println(a)
|
||||
4 | }
|
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
a := [1,2,3,4].filter(fn(a int, b int) bool { return a > 0 })
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/array_filter_anon_fn_err_b.v:2:23: error: type mismatch, should use `fn(a int) bool {...}`
|
||||
1 | fn main() {
|
||||
2 | a := [1,2,3,4].filter(fn(a string) bool { return a.len > 0 })
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
3 | println(a)
|
||||
4 | }
|
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
a := [1,2,3,4].filter(fn(a string) bool { return a.len > 0 })
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/array_filter_fn_err_a.v:5:23: error: function needs exactly 1 argument
|
||||
3 | }
|
||||
4 | fn main() {
|
||||
5 | a := [1,2,3,4].filter(fil)
|
||||
| ~~~~~
|
||||
6 | println(a)
|
||||
7 | }
|
|
@ -0,0 +1,7 @@
|
|||
fn fil(a int, b int) bool {
|
||||
return a > 0
|
||||
}
|
||||
fn main() {
|
||||
a := [1,2,3,4].filter(fil)
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/array_filter_fn_err_b.v:5:23: error: type mismatch, should use `fn(a int) bool {...}`
|
||||
3 | }
|
||||
4 | fn main() {
|
||||
5 | a := [1,2,3,4].filter(fil)
|
||||
| ~~~~~
|
||||
6 | println(a)
|
||||
7 | }
|
|
@ -0,0 +1,7 @@
|
|||
fn fil(a string) bool {
|
||||
return a.len > 0
|
||||
}
|
||||
fn main() {
|
||||
a := [1,2,3,4].filter(fil)
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/array_map_anon_fn_err_a.v:2:20: error: function needs exactly 1 argument
|
||||
1 | fn main() {
|
||||
2 | a := [1,2,3,4].map(fn(a int, b int) int {return a + b})
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
3 | println(a)
|
||||
4 | }
|
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
a := [1,2,3,4].map(fn(a int, b int) int {return a + b})
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/array_map_anon_fn_err_b.v:2:20: error: type mismatch, should use `fn(a int) int {...}`
|
||||
1 | fn main() {
|
||||
2 | a := [1,2,3,4].map(fn(a string) string { return a })
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
3 | println(a)
|
||||
4 | }
|
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
a := [1,2,3,4].map(fn(a string) string { return a })
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/array_map_fn_err_a.v:5:20: error: function needs exactly 1 argument
|
||||
3 | }
|
||||
4 | fn main() {
|
||||
5 | a := [1,2,3,4].map(add)
|
||||
| ~~~~~
|
||||
6 | println(a)
|
||||
7 | }
|
|
@ -0,0 +1,7 @@
|
|||
fn add(a int, b int) int {
|
||||
return a + b
|
||||
}
|
||||
fn main() {
|
||||
a := [1,2,3,4].map(add)
|
||||
println(a)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/array_map_fn_err_b.v:5:20: error: type mismatch, should use `fn(a int) int {...}`
|
||||
3 | }
|
||||
4 | fn main() {
|
||||
5 | a := [1,2,3,4].map(add)
|
||||
| ~~~~~
|
||||
6 | println(a)
|
||||
7 | }
|
|
@ -0,0 +1,7 @@
|
|||
fn add(a string) string {
|
||||
return a
|
||||
}
|
||||
fn main() {
|
||||
a := [1,2,3,4].map(add)
|
||||
println(a)
|
||||
}
|
Loading…
Reference in New Issue