sort: handle `.sort(a.field > b.field)`
parent
4bc0dde413
commit
e5e31f7210
|
@ -539,6 +539,16 @@ fn compare_ints(a, b &int) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
fn compare_ints_reverse(a, b &int) int {
|
||||
if *a > *b {
|
||||
return -1
|
||||
}
|
||||
if *a < *b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fn compare_floats(a, b &f64) int {
|
||||
if *a < *b {
|
||||
return -1
|
||||
|
@ -549,6 +559,16 @@ fn compare_floats(a, b &f64) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
fn compare_floats_reverse(a, b &f64) int {
|
||||
if *a > *b {
|
||||
return -1
|
||||
}
|
||||
if *a < *b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// []int.sort sorts array of int in place in ascending order.
|
||||
pub fn (mut a []int) sort() {
|
||||
a.sort_with_compare(compare_ints)
|
||||
|
|
|
@ -695,6 +695,11 @@ fn test_eq() {
|
|||
*/
|
||||
}
|
||||
|
||||
struct User {
|
||||
age int
|
||||
name string
|
||||
}
|
||||
|
||||
fn test_sort() {
|
||||
mut a := ['hi', '1', '5', '3']
|
||||
a.sort()
|
||||
|
@ -717,6 +722,20 @@ fn test_sort() {
|
|||
assert nums[2] == 42
|
||||
assert nums[3] == 67
|
||||
assert nums[4] == 108
|
||||
//
|
||||
mut users := [User{22, 'Peter'}, User{20, 'Bob'}, User{25, 'Alice'}]
|
||||
users.sort(a.age < b.age)
|
||||
assert(users[0].age == 20)
|
||||
assert(users[1].age == 22)
|
||||
assert(users[2].age == 25)
|
||||
assert(users[0].name == 'Bob')
|
||||
assert(users[1].name == 'Peter')
|
||||
assert(users[2].name == 'Alice')
|
||||
//
|
||||
users.sort(a.age > b.age)
|
||||
assert(users[0].age == 25)
|
||||
assert(users[1].age == 22)
|
||||
assert(users[2].age == 20)
|
||||
}
|
||||
|
||||
fn test_f32_sort() {
|
||||
|
|
|
@ -109,10 +109,10 @@ pub fn (mut cmd Command) parse(args []string) {
|
|||
}
|
||||
cmd.add_default_commands()
|
||||
if cmd.sort_flags {
|
||||
cmd.flags.sort()
|
||||
cmd.flags.sort(a.name < b.name)
|
||||
}
|
||||
if cmd.sort_commands {
|
||||
cmd.commands.sort()
|
||||
cmd.commands.sort(a.name < b.name)
|
||||
}
|
||||
cmd.args = args[1..]
|
||||
for i in 0 .. cmd.commands.len {
|
||||
|
@ -286,8 +286,3 @@ fn (cmds []Command) contains(name string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn (mut cmds []Command) sort() {
|
||||
cmds.sort_with_compare(fn (a, b &Command) int {
|
||||
return compare_strings(&a.name, &b.name)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ fn flag_should_be_set(cmd cli.Command) ? {
|
|||
flag := cmd.flags.get_string('flag')?
|
||||
assert flag == 'value'
|
||||
}
|
||||
|
||||
|
||||
fn test_if_flag_gets_set() {
|
||||
mut cmd := cli.Command{
|
||||
name: 'command'
|
||||
|
|
|
@ -183,8 +183,3 @@ fn (flags []Flag) contains(name string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn (mut flags []Flag) sort() {
|
||||
flags.sort_with_compare(fn (a, b &Flag) int {
|
||||
return compare_strings(&a.name, &b.name)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -859,6 +859,13 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
} else if is_sort {
|
||||
scope.update_var_type('a', array_info.elem_type)
|
||||
scope.update_var_type('b', array_info.elem_type)
|
||||
// Verify `.sort(a < b)`
|
||||
if call_expr.args.len > 0 {
|
||||
if call_expr.args[0].expr !is ast.InfixExpr {
|
||||
c.error('`.sort()` requires a `<` or `>` comparison as the first and only argument' +
|
||||
'\ne.g. `users.sort(a.id < b.id)`', call_expr.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
elem_typ = array_info.elem_type
|
||||
}
|
||||
|
|
|
@ -3750,12 +3750,14 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
|||
// 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.
|
||||
mut typ := info.elem_type
|
||||
mut is_reverse := false
|
||||
// `users.sort(a.age > b.age)`
|
||||
if node.args.len > 0 {
|
||||
// Get the type of the field that's being compared
|
||||
// `a.age > b.age` => `age int` => int
|
||||
infix_expr := node.args[0].expr as ast.InfixExpr
|
||||
typ = infix_expr.left_type
|
||||
is_reverse = infix_expr.op == .gt
|
||||
}
|
||||
mut compare_fn := match typ {
|
||||
table.int_type {
|
||||
|
@ -3770,12 +3772,15 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
|||
else {
|
||||
q := g.table.get_type_symbol(typ)
|
||||
if node.args.len == 0 {
|
||||
verror('usage: .sort(a.field < b.field)')
|
||||
verror('usage: .sort(a.field < b.field) $q.name')
|
||||
}
|
||||
verror('sort(): unhandled type $typ $q.name')
|
||||
''
|
||||
}
|
||||
}
|
||||
if is_reverse {
|
||||
compare_fn += '_reverse'
|
||||
}
|
||||
//
|
||||
g.write('qsort(')
|
||||
g.expr(node.left)
|
||||
|
|
Loading…
Reference in New Issue