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

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
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.