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)
|
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 {
|
pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
left_type := c.expr(call_expr.left)
|
left_type := c.expr(call_expr.left)
|
||||||
is_generic := left_type == table.t_type
|
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
|
// FIXME: Argument count != 1 will break these
|
||||||
if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',
|
if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',
|
||||||
'map', 'slice'] {
|
'map', 'slice'] {
|
||||||
|
mut elem_typ := table.void_type
|
||||||
if method_name in ['filter', 'map'] {
|
if method_name in ['filter', 'map'] {
|
||||||
array_info := left_type_sym.info as table.Array
|
array_info := left_type_sym.info as table.Array
|
||||||
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||||
scope.update_var_type('it', array_info.elem_type)
|
scope.update_var_type('it', array_info.elem_type)
|
||||||
|
elem_typ = array_info.elem_type
|
||||||
}
|
}
|
||||||
// map/filter are supposed to have 1 arg only
|
// map/filter are supposed to have 1 arg only
|
||||||
mut arg_type := left_type
|
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.return_type = left_type
|
||||||
call_expr.receiver_type = left_type
|
call_expr.receiver_type = left_type
|
||||||
if method_name == 'map' {
|
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)
|
arg_sym := c.table.get_type_symbol(arg_type)
|
||||||
// FIXME: match expr failed for now
|
// FIXME: match expr failed for now
|
||||||
mut ret_type := 0
|
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 }
|
else { ret_type = arg_type }
|
||||||
}
|
}
|
||||||
call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod)
|
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' {
|
} else if method_name == 'clone' {
|
||||||
// need to return `array_xxx` instead of `array`
|
// need to return `array_xxx` instead of `array`
|
||||||
// in ['clone', 'str'] {
|
// 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