all: new `.sort(a < b)` syntax
parent
9800cf1e7b
commit
4bc0dde413
|
@ -539,6 +539,16 @@ fn compare_ints(a, b &int) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
fn compare_floats(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)
|
||||
|
|
|
@ -710,6 +710,13 @@ fn test_sort() {
|
|||
assert nums[2] == 42
|
||||
assert nums[3] == 67
|
||||
assert nums[4] == 108
|
||||
//
|
||||
nums.sort(a < b)
|
||||
assert nums[0] == -3
|
||||
assert nums[1] == 7
|
||||
assert nums[2] == 42
|
||||
assert nums[3] == 67
|
||||
assert nums[4] == 108
|
||||
}
|
||||
|
||||
fn test_f32_sort() {
|
||||
|
|
|
@ -250,7 +250,7 @@ fn compare_rep_index(a, b &RepIndex) int {
|
|||
}
|
||||
|
||||
|
||||
fn (mut a []RepIndex) sort() {
|
||||
fn (mut a []RepIndex) sort2() {
|
||||
a.sort_with_compare(compare_rep_index)
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ pub fn (s string) replace_each(vals []string) string {
|
|||
if idxs.len == 0 {
|
||||
return s
|
||||
}
|
||||
idxs.sort()
|
||||
idxs.sort2()
|
||||
mut b := malloc(new_len + 1) // add a \0 just in case
|
||||
// Fill the new string
|
||||
mut idx_pos := 0
|
||||
|
|
|
@ -15,6 +15,7 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
|
|||
None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf |
|
||||
SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
||||
|
||||
|
||||
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | CompIf | ConstDecl |
|
||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
||||
GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return |
|
||||
|
@ -612,12 +613,13 @@ pub:
|
|||
mod string
|
||||
}
|
||||
|
||||
// filter(), map()
|
||||
/*
|
||||
// filter(), map(), sort()
|
||||
pub struct Lambda {
|
||||
pub:
|
||||
name string
|
||||
}
|
||||
|
||||
*/
|
||||
pub struct AssignStmt {
|
||||
pub:
|
||||
right []Expr
|
||||
|
|
|
@ -847,12 +847,19 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
// TODO: remove this for actual methods, use only for compiler magic
|
||||
// FIXME: Argument count != 1 will break these
|
||||
if left_type_sym.kind == .array &&
|
||||
method_name in ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice'] {
|
||||
method_name in ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort'] {
|
||||
mut elem_typ := table.void_type
|
||||
if method_name in ['filter', 'map'] {
|
||||
is_filter_map := method_name in ['filter', 'map']
|
||||
is_sort := method_name == 'sort'
|
||||
if is_filter_map || is_sort {
|
||||
array_info := left_type_sym.info as table.Array
|
||||
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||
scope.update_var_type('it', array_info.elem_type)
|
||||
if is_filter_map {
|
||||
scope.update_var_type('it', array_info.elem_type)
|
||||
} else if is_sort {
|
||||
scope.update_var_type('a', array_info.elem_type)
|
||||
scope.update_var_type('b', array_info.elem_type)
|
||||
}
|
||||
elem_typ = array_info.elem_type
|
||||
}
|
||||
// map/filter are supposed to have 1 arg only
|
||||
|
|
|
@ -3736,6 +3736,56 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
|||
g.write(tmp)
|
||||
}
|
||||
|
||||
// `users.sort(a.age < b.age)`
|
||||
fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
||||
// println('filter s="$s"')
|
||||
sym := g.table.get_type_symbol(node.return_type)
|
||||
if sym.kind != .array {
|
||||
println(node.name)
|
||||
println(g.typ(node.receiver_type))
|
||||
println(sym.kind)
|
||||
verror('sort() requires an array')
|
||||
}
|
||||
info := sym.info as table.Array
|
||||
// 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
|
||||
// `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
|
||||
}
|
||||
mut compare_fn := match typ {
|
||||
table.int_type {
|
||||
'compare_ints'
|
||||
}
|
||||
table.string_type {
|
||||
'compare_strings'
|
||||
}
|
||||
table.f64_type {
|
||||
'compare_floats'
|
||||
}
|
||||
else {
|
||||
q := g.table.get_type_symbol(typ)
|
||||
if node.args.len == 0 {
|
||||
verror('usage: .sort(a.field < b.field)')
|
||||
}
|
||||
verror('sort(): unhandled type $typ $q.name')
|
||||
''
|
||||
}
|
||||
}
|
||||
//
|
||||
g.write('qsort(')
|
||||
g.expr(node.left)
|
||||
g.write('.data, ')
|
||||
g.expr(node.left)
|
||||
g.write('.len, ')
|
||||
g.expr(node.left)
|
||||
g.writeln('.element_size, $compare_fn);')
|
||||
}
|
||||
|
||||
// `nums.filter(it % 2 == 0)`
|
||||
fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||
tmp := g.new_tmp_var()
|
||||
|
|
|
@ -341,6 +341,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
g.gen_array_filter(node)
|
||||
return
|
||||
}
|
||||
'sort' {
|
||||
g.gen_array_sort(node)
|
||||
return
|
||||
}
|
||||
'insert' {
|
||||
g.gen_array_insert(node)
|
||||
return
|
||||
|
|
|
@ -1133,6 +1133,19 @@ fn (mut p Parser) scope_register_it() {
|
|||
})
|
||||
}
|
||||
|
||||
fn (mut p Parser) scope_register_ab() {
|
||||
p.scope.register('a', ast.Var{
|
||||
name: 'a'
|
||||
pos: p.tok.position()
|
||||
is_used: true
|
||||
})
|
||||
p.scope.register('b', ast.Var{
|
||||
name: 'b'
|
||||
pos: p.tok.position()
|
||||
is_used: true
|
||||
})
|
||||
}
|
||||
|
||||
fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||
p.next()
|
||||
if p.tok.kind == .dollar {
|
||||
|
@ -1149,6 +1162,10 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
// defer {
|
||||
// p.close_scope()
|
||||
// }
|
||||
} else if field_name == 'sort' {
|
||||
p.open_scope()
|
||||
name_pos = p.tok.position()
|
||||
p.scope_register_ab()
|
||||
}
|
||||
// ! in mutable methods
|
||||
if p.tok.kind == .not && p.peek_tok.kind == .lpar {
|
||||
|
@ -1208,7 +1225,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
pos: pos
|
||||
}
|
||||
}
|
||||
if is_filter {
|
||||
if is_filter || field_name == 'sort' {
|
||||
p.close_scope()
|
||||
}
|
||||
return mcall_expr
|
||||
|
|
Loading…
Reference in New Issue