feat(stdlib): sorting toolkit — sort_by/sort_desc_by/sort_with + stable merge sort (#11)
Some checks are pending
docs / build-and-deploy (push) Waiting to run

Grow List sorting from a numeric-only insertion sort into a small,
game-friendly toolkit that sorts records and query results by a key or a
full comparator, stably and in O(n log n).

- List.sort_by(s, keyfn)      ascending by a key (draw order, price)
- List.sort_desc_by(s, keyfn) descending (leaderboards)
- List.sort_with(s, cmpfn)    full cmp(a,b)->int comparator (multi-field)

Comparators/keys are passed as named top-level functions rather than
lambdas, so the toolkit ships without waiting on closures (#1).

Engine: a stable bottom-up merge sort. emit_takeright is the single
place stability is decided ("take the right run's head only on a strict
win" -> equal keys keep prior order). List.sort becomes a hybrid:
insertion sort for n<32, merge sort above; both stable, so output is
unchanged. Key functions must return an integer-ish type; record slices
hold pointer elements, so the key/comparator receives the record pointer.

Tests: selfhost/tests/sort.ludic (scalar large-n, sort_by, sort_desc_by,
stability, sort_with). Docs: list-sort_by/desc_by/with + updated
list-sort. All suites green (28 self-host / 46 test / 29 test-tools);
reseeded, C-free bootstrap fixpoint holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-30 11:39:26 +03:00
parent b5455cd550
commit 4aa2012231
8 changed files with 9622 additions and 7747 deletions

View file

@ -35,6 +35,7 @@ function cmd_selfhost_test() -> int {
print("== the self-host compiler is correct ==")
sh_case("structs", "7 9 109 2 42")
sh_case("slices", "0 20 361 777")
sh_case("sort", "0 39 20 1 2 3 3 1 30 10 20 40 2 8")
sh_case("control", "55 4 15 1")
sh_case("match_bits", "1 2 9 16 4 15")
sh_case("fixed", "2 3 0 6 1")