array: map() function

pull/4663/head
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) { 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 a[i] = a[i]*2 // or val*2, doesn't matter
} }
} }
@ -525,26 +525,19 @@ fn test_filter() {
} }
fn test_map() { fn test_map() {
// QTODO nums := [1, 2, 3, 4, 5, 6]
/* strs := ['v', 'is', 'awesome']
println(1)
a := [1, 2, 3, 4, 5, 6] assert nums.map(it * 10) == [10, 20, 30, 40, 50, 60]
b := a.map(it * 10) assert nums.map('$it') == ['1', '2', '3', '4', '5', '6']
assert b.len == 6 assert nums.map(it % 2 == 0) == [false, true, false, true, false, true]
assert b[0] == 10
assert b[1] == 20 assert strs.map(it.to_upper()) == ['V', 'IS', 'AWESOME']
assert b[2] == 30 assert strs.map(it == 'awesome') == [false, false, true]
c := ['v', 'is', 'awesome'] assert strs.map(7) == [7, 7, 7]
d := c.map(it.to_upper())
assert d[0] == 'V' assert nums == [1, 2, 3, 4, 5, 6]
assert d[1] == 'IS' assert strs == ['v', 'is', 'awesome']
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
*/
} }
fn test_array_str() { 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) left_type_sym := c.table.get_type_symbol(left_type)
method_name := call_expr.name method_name := call_expr.name
// TODO: remove this for actual methods, use only for compiler magic // 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', if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse',
'map', 'slice'] { 'map', 'slice'] {
if method_name in ['filter', 'map'] { 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) 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)
} }
mut arg_type := left_type
for arg in call_expr.args { 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 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'] { // in ['clone', 'str'] {
call_expr.receiver_type = left_type.to_ptr() call_expr.receiver_type = left_type.to_ptr()
// call_expr.return_type = call_expr.receiver_type // 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'] { } else if left_type_sym.kind == .array && method_name in ['first', 'last'] {
info := left_type_sym.info as table.Array info := left_type_sym.info as table.Array
call_expr.return_type = info.elem_type call_expr.return_type = info.elem_type
call_expr.receiver_type = left_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 := 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 && 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(')') 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)` // `nums.filter(it % 2 == 0)`
fn (mut g Gen) gen_filter(node ast.CallExpr) { fn (mut g Gen) gen_filter(node ast.CallExpr) {
tmp := g.new_tmp_var() tmp := g.new_tmp_var()

View File

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