From 3f01e2b79624bd0eb8db28dc7c7bd56422d4484f Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 18 Jun 2020 06:22:34 +0800 Subject: [PATCH] cgen: fix array.insert and arr.prepend --- vlib/builtin/array_test.v | 74 ++++++++++++++++----------------------- vlib/v/gen/cgen.v | 36 +++++++++++++++++-- vlib/v/gen/fn.v | 31 +++++++++++----- 3 files changed, 86 insertions(+), 55 deletions(-) diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index f6f8fab9f3..60b170d85e 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -113,54 +113,40 @@ fn test_push() { assert a.str() == '[1, 3]' } -// TODO array.insert is broken -// Cannot pass literal or primitive type as it cannot be cast to voidptr. -// In the current state only that would work: -// i := 3 -// a.insert(0, &i) -// ---------------------------- -/* fn test_insert() { mut a := [1, 2] a.insert(0, 3) - println(a) + assert a[0] == 3 + assert a[2] == 2 + assert a.len == 3 + a.insert(1, 4) + assert a[1] == 4 + assert a[2] == 1 + assert a.len == 4 + a.insert(4, 5) + assert a[4] == 5 + assert a[3] == 2 + assert a.len == 5 + mut b := []f64{} + assert b.len == 0 + b.insert(0, f64(1.1)) + assert b.len == 1 + assert b[0] == f64(1.1) } -*/ -// fn test_insert() { -// mut a := [1, 2] -// a.insert(0, 3) -// assert a[0] == 3 -// assert a[2] == 2 -// assert a.len == 3 -// a.insert(1, 4) -// assert a[1] == 4 -// assert a[2] == 1 -// assert a.len == 4 -// a.insert(4, 5) -// assert a[4] == 5 -// assert a[3] == 2 -// assert a.len == 5 -// mut b := []f64{} -// assert b.len == 0 -// b.insert(0, f64(1.1)) -// assert b.len == 1 -// assert b[0] == f64(1.1) -// } -// TODO array.prepend is broken -// It depends on array.insert -// ----------------------------- -// fn test_prepend() { -// mut a := []int{} -// assert a.len == 0 -// a.prepend(1) -// assert a.len == 1 -// assert a[0] == 1 -// mut b := []f64{} -// assert b.len == 0 -// b.prepend(f64(1.1)) -// assert b.len == 1 -// assert b[0] == f64(1.1) -// } + +fn test_prepend() { + mut a := []int{} + assert a.len == 0 + a.prepend(1) + assert a.len == 1 + assert a[0] == 1 + mut b := []f64{} + assert b.len == 0 + b.prepend(f64(1.1)) + assert b.len == 1 + assert b[0] == f64(1.1) +} + fn test_strings() { a := ['a', 'b', 'c'] assert a.str() == "['a', 'b', 'c']" diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 434b85ee8a..c95496fb5d 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -3069,7 +3069,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool { } // `nums.map(it % 2 == 0)` -fn (mut g Gen) gen_map(node ast.CallExpr) { +fn (mut g Gen) gen_array_map(node ast.CallExpr) { tmp := g.new_tmp_var() s := g.go_before_stmt(0) // println('filter s="$s"') @@ -3127,7 +3127,7 @@ fn (mut g Gen) gen_map(node ast.CallExpr) { } // `nums.filter(it % 2 == 0)` -fn (mut g Gen) gen_filter(node ast.CallExpr) { +fn (mut g Gen) gen_array_filter(node ast.CallExpr) { tmp := g.new_tmp_var() s := g.go_before_stmt(0) // println('filter s="$s"') @@ -3177,6 +3177,38 @@ fn (mut g Gen) gen_filter(node ast.CallExpr) { g.write(tmp) } +// `nums.insert(0, 2)` +fn (mut g Gen) gen_array_insert(node ast.CallExpr) { + sym := g.table.get_type_symbol(node.left_type) + if sym.kind != .array { + verror('insert() requires an array') + } + info := sym.info as table.Array + elem_type_str := g.typ(info.elem_type) + g.write('array_insert(&') + g.expr(node.left) + g.write(', ') + g.expr(node.args[0].expr) + g.write(', &($elem_type_str[]){') + g.expr(node.args[1].expr) + g.write('});') +} + +// `nums.prepend(2)` +fn (mut g Gen) gen_array_prepend(node ast.CallExpr) { + sym := g.table.get_type_symbol(node.left_type) + if sym.kind != .array { + verror('prepend() requires an array') + } + info := sym.info as table.Array + elem_type_str := g.typ(info.elem_type) + g.write('array_prepend(&') + g.expr(node.left) + g.write(', &($elem_type_str[]){') + g.expr(node.args[0].expr) + g.write('});') +} + [inline] fn (g &Gen) nth_stmt_pos(n int) int { return g.stmt_path_pos[g.stmt_path_pos.len - (1 + n)] diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 28fc2a5524..44ddb4a780 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -359,14 +359,27 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.write(')') 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) - return + left_sym := g.table.get_type_symbol(node.left_type) + if left_sym.kind == .array { + match node.name { + 'filter' { + g.gen_array_filter(node) + return + } + 'insert' { + g.gen_array_insert(node) + return + } + 'map' { + g.gen_array_map(node) + return + } + 'prepend' { + g.gen_array_prepend(node) + return + } + else {} + } } if node.name == 'str' { mut styp := g.typ(node.receiver_type) @@ -376,7 +389,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.gen_str_for_type_with_styp(node.receiver_type, styp) } // TODO performance, detect `array` method differently - if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', + if left_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last',