sort: handle `.sort(a.field > b.field)`
parent
4bc0dde413
commit
e5e31f7210
|
@ -539,6 +539,16 @@ fn compare_ints(a, b &int) int {
|
||||||
return 0
|
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 {
|
fn compare_floats(a, b &f64) int {
|
||||||
if *a < *b {
|
if *a < *b {
|
||||||
return -1
|
return -1
|
||||||
|
@ -549,6 +559,16 @@ fn compare_floats(a, b &f64) int {
|
||||||
return 0
|
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.
|
// []int.sort sorts array of int in place in ascending order.
|
||||||
pub fn (mut a []int) sort() {
|
pub fn (mut a []int) sort() {
|
||||||
a.sort_with_compare(compare_ints)
|
a.sort_with_compare(compare_ints)
|
||||||
|
|
|
@ -695,6 +695,11 @@ fn test_eq() {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
age int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
fn test_sort() {
|
fn test_sort() {
|
||||||
mut a := ['hi', '1', '5', '3']
|
mut a := ['hi', '1', '5', '3']
|
||||||
a.sort()
|
a.sort()
|
||||||
|
@ -717,6 +722,20 @@ fn test_sort() {
|
||||||
assert nums[2] == 42
|
assert nums[2] == 42
|
||||||
assert nums[3] == 67
|
assert nums[3] == 67
|
||||||
assert nums[4] == 108
|
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() {
|
fn test_f32_sort() {
|
||||||
|
|
|
@ -109,10 +109,10 @@ pub fn (mut cmd Command) parse(args []string) {
|
||||||
}
|
}
|
||||||
cmd.add_default_commands()
|
cmd.add_default_commands()
|
||||||
if cmd.sort_flags {
|
if cmd.sort_flags {
|
||||||
cmd.flags.sort()
|
cmd.flags.sort(a.name < b.name)
|
||||||
}
|
}
|
||||||
if cmd.sort_commands {
|
if cmd.sort_commands {
|
||||||
cmd.commands.sort()
|
cmd.commands.sort(a.name < b.name)
|
||||||
}
|
}
|
||||||
cmd.args = args[1..]
|
cmd.args = args[1..]
|
||||||
for i in 0 .. cmd.commands.len {
|
for i in 0 .. cmd.commands.len {
|
||||||
|
@ -286,8 +286,3 @@ fn (cmds []Command) contains(name string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut cmds []Command) sort() {
|
|
||||||
cmds.sort_with_compare(fn (a, b &Command) int {
|
|
||||||
return compare_strings(&a.name, &b.name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -183,8 +183,3 @@ fn (flags []Flag) contains(name string) bool {
|
||||||
return false
|
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 {
|
} else if is_sort {
|
||||||
scope.update_var_type('a', array_info.elem_type)
|
scope.update_var_type('a', array_info.elem_type)
|
||||||
scope.update_var_type('b', 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
|
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()`)
|
// 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_reverse := false
|
||||||
// `users.sort(a.age > b.age)`
|
// `users.sort(a.age > b.age)`
|
||||||
if node.args.len > 0 {
|
if node.args.len > 0 {
|
||||||
// Get the type of the field that's being compared
|
// Get the type of the field that's being compared
|
||||||
// `a.age > b.age` => `age int` => int
|
// `a.age > b.age` => `age int` => int
|
||||||
infix_expr := node.args[0].expr as ast.InfixExpr
|
infix_expr := node.args[0].expr as ast.InfixExpr
|
||||||
typ = infix_expr.left_type
|
typ = infix_expr.left_type
|
||||||
|
is_reverse = infix_expr.op == .gt
|
||||||
}
|
}
|
||||||
mut compare_fn := match typ {
|
mut compare_fn := match typ {
|
||||||
table.int_type {
|
table.int_type {
|
||||||
|
@ -3770,12 +3772,15 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
||||||
else {
|
else {
|
||||||
q := g.table.get_type_symbol(typ)
|
q := g.table.get_type_symbol(typ)
|
||||||
if node.args.len == 0 {
|
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')
|
verror('sort(): unhandled type $typ $q.name')
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if is_reverse {
|
||||||
|
compare_fn += '_reverse'
|
||||||
|
}
|
||||||
//
|
//
|
||||||
g.write('qsort(')
|
g.write('qsort(')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
|
|
Loading…
Reference in New Issue