Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
checker, cgen: implement methods reverse()/reverse_in_place() for fix…
Browse files Browse the repository at this point in the history
…ed array
yuyi98 committed Oct 31, 2024
1 parent 4e9b21f commit 1087964
Showing 5 changed files with 105 additions and 2 deletions.
52 changes: 52 additions & 0 deletions vlib/builtin/fixed_array_reverse_test.v
Original file line number Diff line number Diff line change
@@ -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'
}
2 changes: 1 addition & 1 deletion vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
@@ -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',
10 changes: 10 additions & 0 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
@@ -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
}
37 changes: 36 additions & 1 deletion vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
@@ -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()
6 changes: 6 additions & 0 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 1087964

Please sign in to comment.