diff --git a/vlib/builtin/fixed_array_reverse_test.v b/vlib/builtin/fixed_array_reverse_test.v new file mode 100644 index 0000000000..9b6c46a36f --- /dev/null +++ b/vlib/builtin/fixed_array_reverse_test.v @@ -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' +} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index c68238a663..2347ec099c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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', diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 69f1483411..53d0cd8bf3 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -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 } diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index cacd3e2cc6..e11bbdd6a0 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -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() diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index f86ab3fea1..0f9d32a00e 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -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 }