From 066384ce8c13bcac052d60f1983f40674ba9b698 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 27 Nov 2024 16:03:14 -0300 Subject: [PATCH] checker: allow array sort with callexpr (#22989) --- vlib/v/checker/fn.v | 6 +++--- vlib/v/checker/tests/array_fancy_sort_err.out | 20 ++++++++++++++++--- vlib/v/checker/tests/array_fancy_sort_err.vv | 2 +- vlib/v/gen/c/array.v | 2 +- .../array_sort_with_call_test.v | 16 +++++++++++++++ 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/builtin_arrays/array_sort_with_call_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index b6464678a..04bcf09d2 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -3437,9 +3437,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as } else if left_name == right_name { c.error('`.${method_name}()` cannot use same argument', node.pos) } - if node.args[0].expr.left !in [ast.Ident, ast.SelectorExpr, ast.IndexExpr] - || node.args[0].expr.right !in [ast.Ident, ast.SelectorExpr, ast.IndexExpr] { - c.error('`.${method_name}()` can only use ident, index or selector as argument, \ne.g. `arr.${method_name}(a < b)`, `arr.${method_name}(a.id < b.id)`, `arr.${method_name}(a[0] < b[0])`', + if node.args[0].expr.left !in [ast.CallExpr, ast.Ident, ast.SelectorExpr, ast.IndexExpr] + || node.args[0].expr.right !in [ast.CallExpr, ast.Ident, ast.SelectorExpr, ast.IndexExpr] { + c.error('`.${method_name}()` can only use ident, index, selector or call as argument, \ne.g. `arr.${method_name}(a < b)`, `arr.${method_name}(a.id < b.id)`, `arr.${method_name}(a[0] < b[0])`', node.pos) } } else { diff --git a/vlib/v/checker/tests/array_fancy_sort_err.out b/vlib/v/checker/tests/array_fancy_sort_err.out index c11bc8053..29f6b821f 100644 --- a/vlib/v/checker/tests/array_fancy_sort_err.out +++ b/vlib/v/checker/tests/array_fancy_sort_err.out @@ -1,8 +1,22 @@ -vlib/v/checker/tests/array_fancy_sort_err.vv:6:8: error: `.sort()` can only use ident, index or selector as argument, +vlib/v/checker/tests/array_fancy_sort_err.vv:6:8: error: `.sort()` can only use `a` or `b` as argument, e.g. `arr.sort(a < b)` + 4 | text := os.read_file(os.args[0])! + 5 | mut lines := text.split_into_lines() + 6 | lines.sort((go a.split('/').last()) < b.split('/').last()) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 7 | println(lines.join('\n')) + 8 | } +vlib/v/checker/tests/array_fancy_sort_err.vv:6:8: error: `.sort()` can only use ident, index, selector or call as argument, e.g. `arr.sort(a < b)`, `arr.sort(a.id < b.id)`, `arr.sort(a[0] < b[0])` 4 | text := os.read_file(os.args[0])! 5 | mut lines := text.split_into_lines() - 6 | lines.sort(a.split('/').last() < b.split('/').last()) - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 6 | lines.sort((go a.split('/').last()) < b.split('/').last()) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 7 | println(lines.join('\n')) + 8 | } +vlib/v/checker/tests/array_fancy_sort_err.vv:6:13: error: infix expr: cannot use `string` (right expression) as `thread string` + 4 | text := os.read_file(os.args[0])! + 5 | mut lines := text.split_into_lines() + 6 | lines.sort((go a.split('/').last()) < b.split('/').last()) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | println(lines.join('\n')) 8 | } diff --git a/vlib/v/checker/tests/array_fancy_sort_err.vv b/vlib/v/checker/tests/array_fancy_sort_err.vv index d945cbe42..440324077 100644 --- a/vlib/v/checker/tests/array_fancy_sort_err.vv +++ b/vlib/v/checker/tests/array_fancy_sort_err.vv @@ -3,6 +3,6 @@ import os fn main() { text := os.read_file(os.args[0])! mut lines := text.split_into_lines() - lines.sort(a.split('/').last() < b.split('/').last()) + lines.sort((go a.split('/').last()) < b.split('/').last()) println(lines.join('\n')) } diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 4eff6bc9a..ecc12945f 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -707,7 +707,7 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) { left_name := infix_expr.left.str() if left_name.len > 1 { compare_fn += '_by' + - left_name[1..].replace_each(['.', '_', '[', '_', ']', '_', "'", '_', '"', '_', '(', '', ')', '', ',', '']) + left_name[1..].replace_each(['.', '_', '[', '_', ']', '_', "'", '_', '"', '_', '(', '', ')', '', ',', '', '/', '_']) } // is_reverse is `true` for `.sort(a > b)` and `.sort(b < a)` is_reverse := (left_name.starts_with('a') && infix_expr.op == .gt) diff --git a/vlib/v/tests/builtin_arrays/array_sort_with_call_test.v b/vlib/v/tests/builtin_arrays/array_sort_with_call_test.v new file mode 100644 index 000000000..38567e7c6 --- /dev/null +++ b/vlib/v/tests/builtin_arrays/array_sort_with_call_test.v @@ -0,0 +1,16 @@ +struct AB { + a int + b int +} + +fn (ab AB) value() int { + return ab.a + ab.b +} + +fn test_main() { + mut values := [AB{5, 6}, AB{3, 4}, AB{1, 2}] + values.sort(a.value() < b.value()) + assert values[0] == AB{1, 2} + assert values[1] == AB{3, 4} + assert values[2] == AB{5, 6} +} -- 2.39.5