1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

array: map() function

This commit is contained in:
Tanel Liiv 2020-05-01 01:29:54 +03:00 committed by GitHub
parent 87813e84e9
commit 182e7071bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 28 deletions

View File

@ -340,7 +340,7 @@ fn double_up(a mut []int) {
}
fn double_up_v2(a mut []int) {
for i, val in a {
for i, _ in a {
a[i] = a[i]*2 // or val*2, doesn't matter
}
}
@ -525,26 +525,19 @@ fn test_filter() {
}
fn test_map() {
// QTODO
/*
println(1)
a := [1, 2, 3, 4, 5, 6]
b := a.map(it * 10)
assert b.len == 6
assert b[0] == 10
assert b[1] == 20
assert b[2] == 30
c := ['v', 'is', 'awesome']
d := c.map(it.to_upper())
assert d[0] == 'V'
assert d[1] == 'IS'
assert d[2] == 'AWESOME'
bools := c.map(it == 'v')
assert bools.len == 3
assert bools[0] == true
assert bools[1] == false
assert bools[2] == false
*/
nums := [1, 2, 3, 4, 5, 6]
strs := ['v', 'is', 'awesome']
assert nums.map(it * 10) == [10, 20, 30, 40, 50, 60]
assert nums.map('$it') == ['1', '2', '3', '4', '5', '6']
assert nums.map(it % 2 == 0) == [false, true, false, true, false, true]
assert strs.map(it.to_upper()) == ['V', 'IS', 'AWESOME']
assert strs.map(it == 'awesome') == [false, false, true]
assert strs.map(7) == [7, 7, 7]
assert nums == [1, 2, 3, 4, 5, 6]
assert strs == ['v', 'is', 'awesome']
}
fn test_array_str() {

View File

@ -599,6 +599,7 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
left_type_sym := c.table.get_type_symbol(left_type)
method_name := call_expr.name
// TODO: remove this for actual methods, use only for compiler magic
// FIXME: Argument count != 1 will break these
if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',
'map', 'slice'] {
if method_name in ['filter', 'map'] {
@ -606,24 +607,28 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
mut scope := c.file.scope.innermost(call_expr.pos.pos)
scope.update_var_type('it', array_info.elem_type)
}
mut arg_type := left_type
for arg in call_expr.args {
c.expr(arg.expr)
arg_type = c.expr(arg.expr)
}
// need to return `array_xxx` instead of `array`
call_expr.return_type = left_type
if method_name == 'clone' {
call_expr.receiver_type = left_type
if method_name == 'map' && call_expr.args.len == 1 {
call_expr.return_type = c.table.find_or_register_array(arg_type, 1)
} else if method_name == 'clone' {
// need to return `array_xxx` instead of `array`
// in ['clone', 'str'] {
call_expr.receiver_type = left_type.to_ptr()
// call_expr.return_type = call_expr.receiver_type
} else {
call_expr.receiver_type = left_type
}
return left_type
return call_expr.return_type
} else if left_type_sym.kind == .array && method_name in ['first', 'last'] {
info := left_type_sym.info as table.Array
call_expr.return_type = info.elem_type
call_expr.receiver_type = left_type
return info.elem_type
return call_expr.return_type
}
if method := c.table.type_find_method(left_type_sym, method_name) {
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.mod != c.mod &&

View File

@ -2494,6 +2494,41 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write(')')
}
// `nums.map(it % 2 == 0)`
fn (mut g Gen) gen_map(node ast.CallExpr) {
tmp := g.new_tmp_var()
s := g.out.after(g.stmt_start_pos) // the already generated part of current statement
g.out.go_back(s.len)
// println('filter s="$s"')
ret_typ := g.typ(node.return_type)
//inp_typ := g.typ(node.receiver_type)
ret_sym := g.table.get_type_symbol(node.return_type)
inp_sym := g.table.get_type_symbol(node.receiver_type)
ret_info := ret_sym.info as table.Array
ret_elem_type := g.typ(ret_info.elem_type)
inp_info := inp_sym.info as table.Array
inp_elem_type := g.typ(inp_info.elem_type)
if inp_sym.kind != .array {
verror('map() requires an array')
}
g.writeln('')
g.write('int ${tmp}_len = ')
g.expr(node.left)
g.writeln('.len;')
g.writeln('$ret_typ $tmp = __new_array(0, ${tmp}_len, sizeof($ret_elem_type));')
g.writeln('for (int i = 0; i < ${tmp}_len; i++) {')
g.write('$inp_elem_type it = (($inp_elem_type*) ')
g.expr(node.left)
g.writeln('.data)[i];')
g.write('$ret_elem_type ti = ')
g.expr(node.args[0].expr) // the first arg is the filter condition
g.writeln(';')
g.writeln('array_push(&$tmp, &ti);')
g.writeln('}')
g.write(s)
g.write(tmp)
}
// `nums.filter(it % 2 == 0)`
fn (mut g Gen) gen_filter(node ast.CallExpr) {
tmp := g.new_tmp_var()

View File

@ -242,6 +242,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.write('._object)')
return
}
if typ_sym.kind == .array && node.name == 'map' {
g.gen_map(node)
return
}
// rec_sym := g.table.get_type_symbol(node.receiver_type)
if typ_sym.kind == .array && node.name == 'filter' {
g.gen_filter(node)