all: new `.sort(a < b)` syntax
parent
9800cf1e7b
commit
4bc0dde413
|
@ -539,6 +539,16 @@ fn compare_ints(a, b &int) int {
|
||||||
return 0
|
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.
|
// []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)
|
||||||
|
|
|
@ -710,6 +710,13 @@ 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
|
||||||
|
//
|
||||||
|
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() {
|
fn test_f32_sort() {
|
||||||
|
|
|
@ -126,7 +126,7 @@ pub fn (bp byteptr) vstring() string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: bp
|
||||||
len: unsafe {C.strlen(bp)}
|
len: unsafe {C.strlen(bp)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// byteptr.vstring_with_len() - converts a C style string to a V string. NB: the string data is reused, NOT copied.
|
// byteptr.vstring_with_len() - converts a C style string to a V string. NB: the string data is reused, NOT copied.
|
||||||
|
@ -135,7 +135,7 @@ pub fn (bp byteptr) vstring_with_len(len int) string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: bp
|
||||||
len: len
|
len: len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// string.clone_static returns an independent copy of a given array
|
// string.clone_static returns an independent copy of a given array
|
||||||
|
@ -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)
|
a.sort_with_compare(compare_rep_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ pub fn (s string) replace_each(vals []string) string {
|
||||||
if idxs.len == 0 {
|
if idxs.len == 0 {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
idxs.sort()
|
idxs.sort2()
|
||||||
mut b := malloc(new_len + 1) // add a \0 just in case
|
mut b := malloc(new_len + 1) // add a \0 just in case
|
||||||
// Fill the new string
|
// Fill the new string
|
||||||
mut idx_pos := 0
|
mut idx_pos := 0
|
||||||
|
@ -1446,7 +1446,7 @@ pub fn (s string) repeat(count int) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
new_len := s.len * count
|
new_len := s.len * count
|
||||||
ret[new_len] = 0
|
ret[new_len] = 0
|
||||||
return ret.vstring_with_len(new_len)
|
return ret.vstring_with_len(new_len)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
|
||||||
IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr |
|
IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr |
|
||||||
None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf |
|
None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf |
|
||||||
SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
||||||
|
|
||||||
|
|
||||||
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | CompIf | ConstDecl |
|
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | CompIf | ConstDecl |
|
||||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
||||||
|
@ -612,12 +613,13 @@ pub:
|
||||||
mod string
|
mod string
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter(), map()
|
/*
|
||||||
|
// filter(), map(), sort()
|
||||||
pub struct Lambda {
|
pub struct Lambda {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
pub struct AssignStmt {
|
pub struct AssignStmt {
|
||||||
pub:
|
pub:
|
||||||
right []Expr
|
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
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
// FIXME: Argument count != 1 will break these
|
// FIXME: Argument count != 1 will break these
|
||||||
if left_type_sym.kind == .array &&
|
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
|
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
|
array_info := left_type_sym.info as table.Array
|
||||||
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
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
|
elem_typ = array_info.elem_type
|
||||||
}
|
}
|
||||||
// map/filter are supposed to have 1 arg only
|
// 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)
|
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)`
|
// `nums.filter(it % 2 == 0)`
|
||||||
fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
|
|
|
@ -341,6 +341,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.gen_array_filter(node)
|
g.gen_array_filter(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
'sort' {
|
||||||
|
g.gen_array_sort(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
'insert' {
|
'insert' {
|
||||||
g.gen_array_insert(node)
|
g.gen_array_insert(node)
|
||||||
return
|
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 {
|
fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind == .dollar {
|
if p.tok.kind == .dollar {
|
||||||
|
@ -1149,6 +1162,10 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||||
// defer {
|
// defer {
|
||||||
// p.close_scope()
|
// p.close_scope()
|
||||||
// }
|
// }
|
||||||
|
} else if field_name == 'sort' {
|
||||||
|
p.open_scope()
|
||||||
|
name_pos = p.tok.position()
|
||||||
|
p.scope_register_ab()
|
||||||
}
|
}
|
||||||
// ! in mutable methods
|
// ! in mutable methods
|
||||||
if p.tok.kind == .not && p.peek_tok.kind == .lpar {
|
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
|
pos: pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_filter {
|
if is_filter || field_name == 'sort' {
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
}
|
}
|
||||||
return mcall_expr
|
return mcall_expr
|
||||||
|
|
Loading…
Reference in New Issue