mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
checker, cgen: implement methods reverse()/reverse_in_place() for fixed arrays (#22712)
This commit is contained in:
parent
b210278c31
commit
97941b97f8
5 changed files with 105 additions and 2 deletions
52
vlib/builtin/fixed_array_reverse_test.v
Normal file
52
vlib/builtin/fixed_array_reverse_test.v
Normal file
|
@ -0,0 +1,52 @@
|
|||
struct User {
|
||||
age int
|
||||
name string
|
||||
}
|
||||
|
||||
fn test_fixed_array_reverse_in_place() {
|
||||
mut a := ['hi', '1', '5', '3']!
|
||||
a.reverse_in_place()
|
||||
assert a == ['3', '5', '1', 'hi']!
|
||||
|
||||
mut nums := [67, -3, 108, 42, 7]!
|
||||
nums.reverse_in_place()
|
||||
assert nums == [7, 42, 108, -3, 67]!
|
||||
|
||||
mut users := [User{22, 'Peter'}, User{20, 'Bob'}, User{25, 'Alice'}]!
|
||||
users.reverse_in_place()
|
||||
assert users[0].age == 25
|
||||
assert users[1].age == 20
|
||||
assert users[2].age == 22
|
||||
assert users[0].name == 'Alice'
|
||||
assert users[1].name == 'Bob'
|
||||
assert users[2].name == 'Peter'
|
||||
}
|
||||
|
||||
fn test_fixed_array_reverse() {
|
||||
a := ['hi', '1', '5', '3']!
|
||||
b := a.reverse()
|
||||
assert a == ['hi', '1', '5', '3']!
|
||||
assert b == ['3', '5', '1', 'hi']!
|
||||
|
||||
mut nums := [67, -3, 108, 42, 7]!
|
||||
n := nums.reverse()
|
||||
assert nums == [67, -3, 108, 42, 7]!
|
||||
assert n == [7, 42, 108, -3, 67]!
|
||||
|
||||
mut users := [User{22, 'Peter'}, User{20, 'Bob'}, User{25, 'Alice'}]!
|
||||
u := users.reverse()
|
||||
|
||||
assert users[0].age == 22
|
||||
assert users[1].age == 20
|
||||
assert users[2].age == 25
|
||||
assert users[0].name == 'Peter'
|
||||
assert users[1].name == 'Bob'
|
||||
assert users[2].name == 'Alice'
|
||||
|
||||
assert u[0].age == 25
|
||||
assert u[1].age == 20
|
||||
assert u[2].age == 22
|
||||
assert u[0].name == 'Alice'
|
||||
assert u[1].name == 'Bob'
|
||||
assert u[2].name == 'Peter'
|
||||
}
|
|
@ -33,7 +33,7 @@ pub const array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map'
|
|||
'first', 'last', 'pop', 'delete', 'insert', 'prepend']
|
||||
pub const array_builtin_methods_chk = token.new_keywords_matcher_from_array_trie(array_builtin_methods)
|
||||
pub const fixed_array_builtin_methods = ['contains', 'index', 'any', 'all', 'wait', 'map', 'sort',
|
||||
'sorted', 'sort_with_compare', 'sorted_with_compare']
|
||||
'sorted', 'sort_with_compare', 'sorted_with_compare', 'reverse', 'reverse_in_place']
|
||||
pub const fixed_array_builtin_methods_chk = token.new_keywords_matcher_from_array_trie(fixed_array_builtin_methods)
|
||||
// TODO: remove `byte` from this list when it is no longer supported
|
||||
pub const reserved_type_names = ['byte', 'bool', 'char', 'i8', 'i16', 'int', 'i64', 'u8', 'u16',
|
||||
|
|
|
@ -3668,6 +3668,16 @@ fn (mut c Checker) fixed_array_builtin_method_call(mut node ast.CallExpr, left_t
|
|||
node.receiver_type = node.left_type
|
||||
}
|
||||
}
|
||||
} else if method_name in ['reverse', 'reverse_in_place'] {
|
||||
if node.args.len != 0 {
|
||||
c.error('`.${method_name}` does not have any arguments', node.args[0].pos)
|
||||
} else {
|
||||
if method_name == 'reverse' {
|
||||
node.return_type = node.left_type
|
||||
} else {
|
||||
node.return_type = ast.void_type
|
||||
}
|
||||
}
|
||||
}
|
||||
return node.return_type
|
||||
}
|
||||
|
|
|
@ -803,7 +803,6 @@ fn (mut g Gen) gen_fixed_array_sorted_with_compare(node ast.CallExpr) {
|
|||
})
|
||||
}
|
||||
g.gen_fixed_array_sort_with_compare(node)
|
||||
g.writeln(';')
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_fixed_array_sort_with_compare(node ast.CallExpr) {
|
||||
|
@ -826,6 +825,42 @@ fn (mut g Gen) gen_fixed_array_sort_with_compare(node ast.CallExpr) {
|
|||
g.gen_array_sort_call(node, compare_fn, false)
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_fixed_array_reverse(node ast.CallExpr) {
|
||||
past := g.past_tmp_var_new()
|
||||
defer {
|
||||
g.past_tmp_var_done(past)
|
||||
}
|
||||
atype := g.styp(node.return_type)
|
||||
g.writeln('${atype} ${past.tmp_var};')
|
||||
g.write('memcpy(&${past.tmp_var}, &')
|
||||
g.expr(node.left)
|
||||
g.writeln(', sizeof(${atype}));')
|
||||
|
||||
unsafe {
|
||||
node.left = ast.Expr(ast.Ident{
|
||||
name: past.tmp_var
|
||||
})
|
||||
}
|
||||
g.gen_fixed_array_reverse_in_place(node)
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_fixed_array_reverse_in_place(node ast.CallExpr) {
|
||||
left_sym := g.table.final_sym(node.left_type)
|
||||
info := left_sym.info as ast.ArrayFixed
|
||||
elem_type := info.elem_type
|
||||
elem_styp := g.styp(elem_type)
|
||||
tmp_var := g.new_tmp_var()
|
||||
g.writeln('${elem_styp} ${tmp_var};')
|
||||
i := g.new_tmp_var()
|
||||
left_var := g.expr_string(node.left)
|
||||
g.empty_line = true
|
||||
g.writeln('for (int ${i} = 0; ${i} < ${info.size}/2; ++${i}) {')
|
||||
g.writeln('\tmemcpy(&${tmp_var}, &${left_var}[${i}], sizeof(${elem_styp}));')
|
||||
g.writeln('\tmemcpy(&${left_var}[${i}], &${left_var}[${info.size}-${i}-1], sizeof(${elem_styp}));')
|
||||
g.writeln('\tmemcpy(&${left_var}[${info.size}-${i}-1], &${tmp_var}, sizeof(${elem_styp}));')
|
||||
g.writeln('}')
|
||||
}
|
||||
|
||||
// `nums.filter(it % 2 == 0)`
|
||||
fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||
past := g.past_tmp_var_new()
|
||||
|
|
|
@ -1216,6 +1216,12 @@ fn (mut g Gen) gen_fixed_array_method_call(node ast.CallExpr, left_type ast.Type
|
|||
'sorted_with_compare' {
|
||||
g.gen_fixed_array_sorted_with_compare(node)
|
||||
}
|
||||
'reverse' {
|
||||
g.gen_fixed_array_reverse(node)
|
||||
}
|
||||
'reverse_in_place' {
|
||||
g.gen_fixed_array_reverse_in_place(node)
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue