diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index aedba056e6..7e60133cb1 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -136,11 +136,7 @@ pub fn (mut a array) sort_with_compare(compare voidptr) { C.qsort(a.data, a.len, a.element_size, compare) } -// 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) +// array.insert pub fn (mut a array) insert(i int, val voidptr) { $if !no_bounds_checking? { if i < 0 || i > a.len { @@ -154,12 +150,30 @@ pub fn (mut a array) insert(i int, val voidptr) { a.len++ } -// TODO array.prepend is broken -// It depends on array.insert +// array.insert_many +pub fn (mut a array) insert_many(i int, val voidptr, size int) { + $if !no_bounds_checking? { + if i < 0 || i > a.len { + panic('array.insert_many: index out of range (i == $i, a.len == $a.len)') + } + } + a.ensure_cap(a.len + size) + elem_size := a.element_size + C.memmove(byteptr(a.data) + (i + size) * elem_size, byteptr(a.data) + i * elem_size, (a.len - i) * elem_size) + C.memcpy(byteptr(a.data) + i * elem_size, val, size * elem_size) + a.len += size +} + +// array.prepend pub fn (mut a array) prepend(val voidptr) { a.insert(0, val) } +// array.prepend_many +pub fn (mut a array) prepend_many(val voidptr, size int) { + a.insert_many(0, val, size) +} + // array.delete deletes array element at the given index pub fn (mut a array) delete(i int) { $if !no_bounds_checking? { diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 60b170d85e..4c3cea21b9 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -134,6 +134,15 @@ fn test_insert() { assert b[0] == f64(1.1) } +fn test_insert_many() { + mut a := [3, 4] + a.insert(0, [1, 2]) + assert a == [1,2,3,4] + b := [5,6] + a.insert(1, b) + assert a == [1,5,6,2,3,4] +} + fn test_prepend() { mut a := []int{} assert a.len == 0 @@ -147,6 +156,15 @@ fn test_prepend() { assert b[0] == f64(1.1) } +fn test_prepend_many() { + mut a := [3,4] + a.prepend([1,2]) + assert a == [1,2,3,4] + b := [5,6] + a.prepend(b) + assert a == [5,6,1,2,3,4] +} + fn test_strings() { a := ['a', 'b', 'c'] assert a.str() == "['a', 'b', 'c']" @@ -166,7 +184,6 @@ fn test_compare_ints() { } */ - fn test_repeat() { { a := [0].repeat(5) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c95496fb5d..c3119232c5 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -3177,36 +3177,58 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { g.write(tmp) } -// `nums.insert(0, 2)` +// `nums.insert(0, 2)` `nums.insert(0, [2,3,4])` 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') + left_sym := g.table.get_type_symbol(node.left_type) + left_info := left_sym.info as table.Array + elem_type_str := g.typ(left_info.elem_type) + arg2_sym := g.table.get_type_symbol(node.args[1].typ) + is_arg2_array := arg2_sym.kind == .array + if is_arg2_array { + g.write('array_insert_many(&') + } else { + g.write('array_insert(&') } - 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('});') + if is_arg2_array { + g.write(', ') + g.expr(node.args[1].expr) + g.write('.data, ') + g.expr(node.args[1].expr) + g.write('.len)') + } else { + g.write(', &($elem_type_str[]){') + g.expr(node.args[1].expr) + g.write('})') + } } -// `nums.prepend(2)` +// `nums.prepend(2)` `nums.prepend([2,3,4])` 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') + left_sym := g.table.get_type_symbol(node.left_type) + left_info := left_sym.info as table.Array + elem_type_str := g.typ(left_info.elem_type) + arg_sym := g.table.get_type_symbol(node.args[0].typ) + is_arg_array := arg_sym.kind == .array + if is_arg_array { + g.write('array_prepend_many(&') + } else { + g.write('array_prepend(&') } - 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('});') + if is_arg_array { + g.write(', ') + g.expr(node.args[0].expr) + g.write('.data, ') + g.expr(node.args[0].expr) + g.write('.len)') + } else { + g.write(', &($elem_type_str[]){') + g.expr(node.args[0].expr) + g.write('})') + } } [inline]