diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 53bd661fe4..c59ddd0866 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -1302,6 +1302,13 @@ pub fn types() -> MutMap { Box::new(list_type(flex(TVAR1))), ); + // sortDesc : List (Num a) -> List (Num a) + add_top_level_function_type!( + Symbol::LIST_SORT_DESC, + vec![list_type(num_type(flex(TVAR1)))], + Box::new(list_type(num_type(flex(TVAR1)))) + ); + // find : List elem, (elem -> Bool) -> Result elem [ NotFound ]* { let not_found = SolvedType::TagUnion( diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 0f47ed431a..d61e629291 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -52,6 +52,11 @@ macro_rules! macro_magic { pub fn builtin_dependencies(symbol: Symbol) -> &'static [Symbol] { match symbol { // Symbol::LIST_SORT_ASC => &[Symbol::LIST_SORT_WITH, Symbol::NUM_COMPARE], + Symbol::LIST_SORT_DESC => &[ + Symbol::LIST_SORT_WITH, + Symbol::LIST_SORT_DESC_COMPARE, + Symbol::NUM_COMPARE, + ], Symbol::LIST_PRODUCT => &[Symbol::LIST_WALK, Symbol::NUM_MUL], Symbol::LIST_SUM => &[Symbol::LIST_WALK, Symbol::NUM_ADD], Symbol::LIST_JOIN_MAP => &[Symbol::LIST_WALK, Symbol::LIST_CONCAT], @@ -141,6 +146,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option LIST_WALK_BACKWARDS => list_walk_backwards, LIST_WALK_UNTIL => list_walk_until, LIST_SORT_WITH => list_sort_with, + LIST_SORT_DESC => list_sort_desc, LIST_ANY => list_any, LIST_ALL => list_all, LIST_FIND => list_find, @@ -3418,6 +3424,60 @@ fn list_sort_with(symbol: Symbol, var_store: &mut VarStore) -> Def { lowlevel_2(symbol, LowLevel::ListSortWith, var_store) } +/// List.sortDesc : List (Num a) -> List (Num a) +fn list_sort_desc(symbol: Symbol, var_store: &mut VarStore) -> Def { + let list_var = var_store.fresh(); + let num_var = var_store.fresh(); + let closure_var = var_store.fresh(); + let compare_ret_var = var_store.fresh(); + let ret_var = list_var; + + let closure = Closure(ClosureData { + function_type: closure_var, + closure_type: var_store.fresh(), + closure_ext_var: var_store.fresh(), + return_type: compare_ret_var, + name: Symbol::LIST_SORT_DESC_COMPARE, + recursive: Recursive::NotRecursive, + captured_symbols: vec![(Symbol::ARG_2, num_var)], + arguments: vec![ + (num_var, no_region(Pattern::Identifier(Symbol::ARG_2))), + (num_var, no_region(Pattern::Identifier(Symbol::ARG_3))), + ], + loc_body: { + Box::new(no_region(RunLowLevel { + op: LowLevel::NumCompare, + args: vec![(num_var, Var(Symbol::ARG_3)), (num_var, Var(Symbol::ARG_2))], + ret_var: compare_ret_var, + })) + }, + }); + + let function = ( + var_store.fresh(), + Loc::at_zero(Expr::Var(Symbol::LIST_SORT_WITH)), + var_store.fresh(), + ret_var, + ); + + let body = Expr::Call( + Box::new(function), + vec![ + (list_var, Loc::at_zero(Var(Symbol::ARG_1))), + (closure_var, Loc::at_zero(closure)), + ], + CalledVia::Space, + ); + + defn( + symbol, + vec![(list_var, Symbol::ARG_1)], + var_store, + body, + ret_var, + ) +} + /// List.any: List elem, (elem -> Bool) -> Bool fn list_any(symbol: Symbol, var_store: &mut VarStore) -> Def { lowlevel_2(symbol, LowLevel::ListAny, var_store) diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 2110083ec4..190bd12e64 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -1110,6 +1110,8 @@ define_builtins! { 52 LIST_ALL: "all" 53 LIST_DROP_IF: "dropIf" 54 LIST_DROP_IF_PREDICATE: "#dropIfPred" + 55 LIST_SORT_DESC: "sortDesc" + 56 LIST_SORT_DESC_COMPARE: "#sortDescCompare" } 5 RESULT: "Result" => { 0 RESULT_RESULT: "Result" imported // the Result.Result type alias