builtin: implement array.pop()
parent
de0b96f52c
commit
cf7d03bda6
|
@ -256,6 +256,22 @@ pub fn (a array) last() voidptr {
|
|||
}
|
||||
}
|
||||
|
||||
// array.pop returns the last element of the array, and removes it
|
||||
pub fn (mut a array) pop() voidptr {
|
||||
// in a sense, this is the opposite of `a << x`
|
||||
$if !no_bounds_checking? {
|
||||
if a.len == 0 {
|
||||
panic('array.pop: array is empty')
|
||||
}
|
||||
}
|
||||
new_len := a.len - 1
|
||||
last_elem := unsafe { byteptr(a.data) + (new_len) * a.element_size }
|
||||
a.len = new_len
|
||||
// NB: a.cap is not changed here *on purpose*, so that
|
||||
// further << ops on that array will be more efficient.
|
||||
return memdup(last_elem, a.element_size)
|
||||
}
|
||||
|
||||
// array.slice returns an array using the same buffer as original array
|
||||
// but starting from the `start` element and ending with the element before
|
||||
// the `end` element of the original array with the length and capacity
|
||||
|
|
|
@ -946,3 +946,29 @@ fn test_reverse_in_place() {
|
|||
c.reverse_in_place()
|
||||
assert c == [[5, 6], [3, 4], [1, 2]]
|
||||
}
|
||||
|
||||
fn test_array_int_pop() {
|
||||
mut a := [1,2,3,4,5]
|
||||
assert a.len == 5
|
||||
x := a.last()
|
||||
y := a.pop()
|
||||
assert x == y
|
||||
assert a.len == 4
|
||||
z := a.pop()
|
||||
assert a.len == 3
|
||||
assert z == 4
|
||||
a.pop()
|
||||
a.pop()
|
||||
final := a.pop()
|
||||
assert final == 1
|
||||
}
|
||||
|
||||
fn test_array_string_pop() {
|
||||
mut a := ['abc', 'def', 'xyz']
|
||||
assert a.len == 3
|
||||
assert a.pop() == 'xyz'
|
||||
assert a.pop() == 'def'
|
||||
assert a.pop() == 'abc'
|
||||
assert a.len == 0
|
||||
assert a.cap == 3
|
||||
}
|
||||
|
|
|
@ -859,10 +859,14 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
call_expr.return_type = left_type
|
||||
call_expr.receiver_type = left_type.to_ptr()
|
||||
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', 'pop'] {
|
||||
info := left_type_sym.info as table.Array
|
||||
call_expr.return_type = info.elem_type
|
||||
call_expr.receiver_type = left_type
|
||||
if method_name == 'pop' {
|
||||
call_expr.receiver_type = left_type.to_ptr()
|
||||
} else {
|
||||
call_expr.receiver_type = left_type
|
||||
}
|
||||
return call_expr.return_type
|
||||
} else if left_type_sym.kind == .array && method_name in ['insert', 'prepend'] {
|
||||
array_info := left_type_sym.info as table.Array
|
||||
|
|
|
@ -352,12 +352,12 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
// TODO performance, detect `array` method differently
|
||||
if left_sym.kind == .array && node.name in
|
||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice'] {
|
||||
// && rec_sym.name == 'array' {
|
||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||
// `array_byte_clone` => `array_clone`
|
||||
receiver_type_name = 'array'
|
||||
if node.name in ['last', 'first'] {
|
||||
if node.name in ['last', 'first', 'pop'] {
|
||||
return_type_str := g.typ(node.return_type)
|
||||
g.write('*($return_type_str*)')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue