hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit aa929853fe0a7d7d790b171576a73e33c8d8a6c9
parent 969d54db90a136b30d9fd7cfd4ff38f7f09efe35
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 31 Mar 2021 14:52:04 -0400

sort::sort: basic implementation

This is just an insertion sort.

Diffstat:
Mscripts/gen-stdlib | 1+
Msort/+test.ha | 17+++++++++++++++++
Asort/sort.ha | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mstdlib.mk | 4+++-
4 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -461,6 +461,7 @@ slice() { gensrcs_sort() { gen_srcs sort \ search.ha \ + sort.ha \ $* } diff --git a/sort/+test.ha b/sort/+test.ha @@ -15,3 +15,20 @@ fn ncmp(a: const *void, b: const *void) int = { const key = 1337; assert(search(nums[..], size(int), &key, &ncmp) == null); }; + +fn io::errorln(items: str...) void; +fn strconv::itos(in: int) str; + +@test fn sort() void = { + let nums = [ + 1, 6, 10, 7, 8, 10, 10, 3, 7, 5, 5, 8, 1, 1, 1, 9, 2, 3, 1, 4, + 2, 1, 5, 3, 2, 5, 10, 1, 7, 6, 8, 10, 6, 5, 7, 4, 3, 9, 9, 4, 7, + 10, 3, 4, 4, 8, 5, 6, 2, 1, 6, 2, 2, 2, 10, 8, 3, 4, 5, 6, 6, 2, + 5, 2, 3, 7, 10, 7, 7, 5, 5, 2, 3, 4, 5, 3, 6, 2, 3, 6, 8, 8, 9, + 7, 10, 4, 10, 3, 2, 7, 10, 8, 8, 2, 2, 5, 3, 7, 4, 1, + ]; + sort(nums[..], size(int), &ncmp); + for (let i = 1z; i < len(nums); i += 1) { + assert(nums[i] >= nums[i - 1]); + }; +}; diff --git a/sort/sort.ha b/sort/sort.ha @@ -0,0 +1,48 @@ +// Sorts a slice of items in place. Provide a slice of 'items', the size of each +// member, and a function to compare one member to another. The 'cmp' function +// will be called with two pointers to values within the items slice, and shall +// return an integer less than, equal to, or greater than zero if the first +// argument is, respectively, less than, equal to, or greater than the second +// argument. +// +// This implementation provides a stable sort. +export fn sort( + items: []void, + itemsz: size, + cmp: *fn(a: const *void, b: const *void) int, +) void = { + if (len(items) < 256) { + insort(items, itemsz, cmp); + return; + }; + + // TODO: Timsort + insort(items, itemsz, cmp); +}; + +fn swap(a: *void, b: *void, sz: size) void = { + let a = a: *[*]u8, b = b: *[*]u8; + for (let i = 0z; i < sz; i += 1) { + let c = a[i]; + a[i] = b[i]; + b[i] = c; + }; +}; + +fn insort( + items: []void, + itemsz: size, + cmp: *fn(a: const *void, b: const *void) int, +) void = { + let ba = items: *[*]u8; + for (let i = 0z; i < len(items); i += 1) { + for (let j = i; j > 0; j -= 1) { + let a = &ba[(j - 1) * itemsz]; + let b = &ba[j * itemsz]; + if (cmp(a, b) <= 0) { + break; + }; + swap(a, b, itemsz); + }; + }; +}; diff --git a/stdlib.mk b/stdlib.mk @@ -611,7 +611,8 @@ $(HARECACHE)/slice/slice.ssa: $(stdlib_slice_srcs) $(stdlib_rt) # sort stdlib_sort_srcs= \ - $(STDLIB)/sort/search.ha + $(STDLIB)/sort/search.ha \ + $(STDLIB)/sort/sort.ha $(HARECACHE)/sort/sort.ssa: $(stdlib_sort_srcs) $(stdlib_rt) @printf 'HAREC \t$@\n' @@ -1354,6 +1355,7 @@ $(TESTCACHE)/slice/slice.ssa: $(testlib_slice_srcs) $(testlib_rt) # sort testlib_sort_srcs= \ $(STDLIB)/sort/search.ha \ + $(STDLIB)/sort/sort.ha \ $(STDLIB)/sort/+test.ha $(TESTCACHE)/sort/sort.ssa: $(testlib_sort_srcs) $(testlib_rt)