mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: fix sorting arrays of primitives (#8204)
This commit is contained in:
parent
190bb38087
commit
f059a9e96c
@ -18,6 +18,25 @@ fn test_sorting_with_condition_expression() {
|
|||||||
assert a == sorted_desc
|
assert a == sorted_desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_sorting_primitives_with_condition_expression() {
|
||||||
|
mut x := ['9', '87', '3210', '654']
|
||||||
|
x.sort(a.len < b.len)
|
||||||
|
assert x == ['9', '87', '654', '3210']
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_score(word string) int {
|
||||||
|
mut total := 0
|
||||||
|
for letter in word {
|
||||||
|
total += int(letter) - 97
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_sorting_with_fn_call_in_condition_expression() {
|
||||||
|
mut words := ['aaaa', 'a', 'b', 'foo', 'bar']
|
||||||
|
words.sort(get_score(a) < get_score(b))
|
||||||
|
}
|
||||||
|
|
||||||
fn mysort(mut a []int) {
|
fn mysort(mut a []int) {
|
||||||
a.sort()
|
a.sort()
|
||||||
}
|
}
|
||||||
|
@ -2700,13 +2700,13 @@ fn scope_register_ab(mut s ast.Scope, pos token.Position, typ table.Type) {
|
|||||||
s.register(ast.Var{
|
s.register(ast.Var{
|
||||||
name: 'a'
|
name: 'a'
|
||||||
pos: pos
|
pos: pos
|
||||||
typ: typ
|
typ: typ.to_ptr()
|
||||||
is_used: true
|
is_used: true
|
||||||
})
|
})
|
||||||
s.register(ast.Var{
|
s.register(ast.Var{
|
||||||
name: 'b'
|
name: 'b'
|
||||||
pos: pos
|
pos: pos
|
||||||
typ: typ
|
typ: typ.to_ptr()
|
||||||
is_used: true
|
is_used: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -219,35 +219,32 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
|||||||
// No arguments means we are sorting an array of builtins (e.g. `numbers.sort()`)
|
// No arguments means we are sorting an array of builtins (e.g. `numbers.sort()`)
|
||||||
// The type for the comparison fns is the type of the element itself.
|
// The type for the comparison fns is the type of the element itself.
|
||||||
mut typ := info.elem_type
|
mut typ := info.elem_type
|
||||||
|
mut is_default := false
|
||||||
mut is_reverse := false
|
mut is_reverse := false
|
||||||
// `users.sort(a.age > b.age)`
|
mut compare_fn := ''
|
||||||
if node.args.len > 0 {
|
if node.args.len == 0 {
|
||||||
// Get the type of the field that's being compared
|
is_default = true
|
||||||
// `a.age > b.age` => `age int` => int
|
} else {
|
||||||
infix_expr := node.args[0].expr as ast.InfixExpr
|
infix_expr := node.args[0].expr as ast.InfixExpr
|
||||||
// typ = infix_expr.left_type
|
is_default = '$infix_expr.left' in ['a', 'b'] && '$infix_expr.right' in ['a', 'b']
|
||||||
is_reverse = infix_expr.op == .gt
|
is_reverse = infix_expr.op == .gt
|
||||||
}
|
}
|
||||||
mut compare_fn := ''
|
if is_default {
|
||||||
match typ {
|
// users.sort() or users.sort(a > b)
|
||||||
table.int_type {
|
compare_fn = match typ {
|
||||||
compare_fn = 'compare_ints'
|
table.int_type, table.int_type.to_ptr() { 'compare_ints' }
|
||||||
|
table.u64_type, table.u64_type.to_ptr() { 'compare_u64s' }
|
||||||
|
table.string_type, table.string_type.to_ptr() { 'compare_strings' }
|
||||||
|
table.f64_type, table.f64_type.to_ptr() { 'compare_floats' }
|
||||||
|
else { '' }
|
||||||
}
|
}
|
||||||
table.u64_type {
|
if compare_fn != '' && is_reverse {
|
||||||
compare_fn = 'compare_u64s'
|
compare_fn += '_reverse'
|
||||||
}
|
}
|
||||||
table.string_type {
|
|
||||||
compare_fn = 'compare_strings'
|
|
||||||
}
|
}
|
||||||
table.f64_type {
|
if compare_fn == '' {
|
||||||
compare_fn = 'compare_floats'
|
// `users.sort(a.age > b.age)`
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Generate a comparison function for a custom type
|
// Generate a comparison function for a custom type
|
||||||
if node.args.len == 0 {
|
|
||||||
verror('usage: .sort(a.field < b.field)')
|
|
||||||
}
|
|
||||||
// verror('sort(): unhandled type $typ $q.name')
|
|
||||||
tmp_name := g.new_tmp_var()
|
tmp_name := g.new_tmp_var()
|
||||||
compare_fn = 'compare_${tmp_name}_' + g.typ(typ)
|
compare_fn = 'compare_${tmp_name}_' + g.typ(typ)
|
||||||
if is_reverse {
|
if is_reverse {
|
||||||
@ -267,10 +264,8 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
|||||||
g.definitions.writeln('\tif (${styp}__gt(*a, *b)) { return -1; } else { return 1; }}')
|
g.definitions.writeln('\tif (${styp}__gt(*a, *b)) { return -1; } else { return 1; }}')
|
||||||
} else {
|
} else {
|
||||||
field_type := g.typ(infix_expr.left_type)
|
field_type := g.typ(infix_expr.left_type)
|
||||||
left_expr_str := g.write_expr_to_string(infix_expr.left).replace_once('.',
|
left_expr_str := g.write_expr_to_string(infix_expr.left)
|
||||||
'->')
|
right_expr_str := g.write_expr_to_string(infix_expr.right)
|
||||||
right_expr_str := g.write_expr_to_string(infix_expr.right).replace_once('.',
|
|
||||||
'->')
|
|
||||||
g.definitions.writeln('$field_type a_ = $left_expr_str;')
|
g.definitions.writeln('$field_type a_ = $left_expr_str;')
|
||||||
g.definitions.writeln('$field_type b_ = $right_expr_str;')
|
g.definitions.writeln('$field_type b_ = $right_expr_str;')
|
||||||
mut op1, mut op2 := '', ''
|
mut op1, mut op2 := '', ''
|
||||||
@ -295,7 +290,6 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
|||||||
g.definitions.writeln('if ($op2) return 1; return 0; }\n')
|
g.definitions.writeln('if ($op2) return 1; return 0; }\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if is_reverse && !compare_fn.ends_with('_reverse') {
|
if is_reverse && !compare_fn.ends_with('_reverse') {
|
||||||
compare_fn += '_reverse'
|
compare_fn += '_reverse'
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user