commit 0248090770511748312ab249bd59eb91351f7f25
parent 2bb24514babdcde6de5a085fdff0395198f9f83e
Author: Sebastian <sebastian@sebsite.pw>
Date: Thu, 14 Sep 2023 00:06:01 -0400
sort::cmp: initial commit
Closes: https://todo.sr.ht/~sircmpwn/hare/780
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
11 files changed, 183 insertions(+), 73 deletions(-)
diff --git a/cmd/hare/deps.ha b/cmd/hare/deps.ha
@@ -7,6 +7,7 @@ use io;
use os;
use path;
use sort;
+use sort::cmp;
use strings;
type deps_fmt = enum {
@@ -156,8 +157,4 @@ fn deps_graph(mods: *[]module::module) void = {
};
// sorts in reverse
-fn revsort(a: const *opaque, b: const *opaque) int = {
- let a = *(a: *(size, str));
- let b = *(b: *(size, str));
- return (b.0 - a.0): int;
-};
+fn revsort(a: const *opaque, b: const *opaque) int = -cmp::sizes(a, b);
diff --git a/cmd/haredoc/doc/util.ha b/cmd/haredoc/doc/util.ha
@@ -8,6 +8,7 @@ use io;
use memio;
use os;
use sort;
+use sort::cmp;
use strings;
// Forked from [[hare::unparse]].
@@ -48,6 +49,6 @@ export fn submodules(path: str) ([]str | error) = {
case let d: fs::dirent =>
append(submodules, strings::dup(d.name));
};
- sort::strings(submodules);
+ sort::sort(submodules, size(str), &cmp::strs);
return submodules;
};
diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha
@@ -14,6 +14,7 @@ use memio;
use os;
use path;
use sort;
+use sort::cmp;
use strconv;
use strings;
use types;
@@ -333,7 +334,8 @@ fn lex_name(lex: *lexer, loc: location) (token | error) = {
let n = memio::string(&buf)!;
- match (sort::searchstrings(bmap[..ltok::LAST_KEYWORD+1], n)) {
+ match (sort::search(bmap[..ltok::LAST_KEYWORD+1],
+ size(str), &n, &cmp::strs)) {
case void =>
return (ltok::NAME, n, loc);
case let i: size =>
diff --git a/hare/module/srcs.ha b/hare/module/srcs.ha
@@ -4,6 +4,7 @@ use hare::ast;
use os;
use path;
use sort;
+use sort::cmp;
use strings;
use time;
@@ -133,11 +134,11 @@ fn path_find(ctx: *context, buf: *path::buffer) (srcset | error) = {
};
};
- sort::strings(res.dirs);
- sort::strings(res.ha);
- sort::strings(res.s);
- sort::strings(res.o);
- sort::strings(res.sc);
+ sort::sort(res.dirs, size(str), &cmp::strs);
+ sort::sort(res.ha, size(str), &cmp::strs);
+ sort::sort(res.s, size(str), &cmp::strs);
+ sort::sort(res.o, size(str), &cmp::strs);
+ sort::sort(res.sc, size(str), &cmp::strs);
return res;
};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -770,7 +770,7 @@ hare_lex() {
gensrcs_hare_lex \
+test.ha
fi
- gen_ssa hare::lex ascii io encoding::utf8 fmt memio sort \
+ gen_ssa hare::lex ascii io encoding::utf8 fmt memio sort sort::cmp \
strconv strings path
}
@@ -785,7 +785,7 @@ hare_module() {
gen_ssa hare::module \
ascii memio bytes datetime encoding::utf8 fmt fs hare::ast hare::lex \
hare::parse hare::unparse io os path strings time time::chrono \
- time::date types encoding::hex
+ time::date types encoding::hex sort sort::cmp
}
gensrcs_hare_parse() {
@@ -1353,10 +1353,15 @@ sort() {
else
gensrcs_sort \
+test.ha
- gen_ssa sort math math::random strings types
+ gen_ssa sort math math::random sort::cmp strings types
fi
}
+sort_cmp() {
+ gen_srcs sort::cmp cmp.ha
+ gen_ssa sort::cmp strings
+}
+
strconv() {
if [ $testing -eq 0 ]
then
@@ -1714,6 +1719,7 @@ path
regex
shlex
sort
+sort::cmp
strconv
strings
strings::template
diff --git a/sort/+test.ha b/sort/+test.ha
@@ -3,6 +3,7 @@
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use math::random;
+use sort::cmp;
use types;
@test fn lbisect() void = {
@@ -10,16 +11,16 @@ use types;
for (let i = 0z; i < len(nums); i += 1) {
if (i != 0 && nums[i - 1] == nums[i]) continue;
const key = nums[i];
- assert(lbisect(nums, size(int), &key, &icmp) == i);
+ assert(lbisect(nums, size(int), &key, &cmp::ints) == i);
};
const n = 0;
- assert(lbisect(nums, size(int), &n, &icmp) == 0);
+ assert(lbisect(nums, size(int), &n, &cmp::ints) == 0);
const n = 6;
- assert(lbisect(nums, size(int), &n, &icmp) == 5);
+ assert(lbisect(nums, size(int), &n, &cmp::ints) == 5);
const n = 8;
- assert(lbisect(nums, size(int), &n, &icmp) == 6);
+ assert(lbisect(nums, size(int), &n, &cmp::ints) == 6);
const n = 12;
- assert(lbisect(nums, size(int), &n, &icmp) == len(nums));
+ assert(lbisect(nums, size(int), &n, &cmp::ints) == len(nums));
};
@test fn rbisect() void = {
@@ -27,27 +28,27 @@ use types;
for (let i = 0z; i < len(nums); i += 1) {
if (i != len(nums) - 1 && nums[i + 1] == nums[i]) continue;
const key = nums[i];
- assert(rbisect(nums, size(int), &key, &icmp) == i + 1);
+ assert(rbisect(nums, size(int), &key, &cmp::ints) == i + 1);
};
const n = 0;
- assert(rbisect(nums, size(int), &n, &icmp) == 0);
+ assert(rbisect(nums, size(int), &n, &cmp::ints) == 0);
const n = 6;
- assert(rbisect(nums, size(int), &n, &icmp) == 5);
+ assert(rbisect(nums, size(int), &n, &cmp::ints) == 5);
const n = 8;
- assert(rbisect(nums, size(int), &n, &icmp) == 6);
+ assert(rbisect(nums, size(int), &n, &cmp::ints) == 6);
const n = 12;
- assert(rbisect(nums, size(int), &n, &icmp) == len(nums));
+ assert(rbisect(nums, size(int), &n, &cmp::ints) == len(nums));
};
@test fn search() void = {
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let i = 0z; i < len(nums); i += 1) {
const key = nums[i];
- const p = search(nums, size(int), &key, &icmp) as size;
+ const p = search(nums, size(int), &key, &cmp::ints) as size;
assert(p == i);
};
const key = 1337;
- assert(search(nums, size(int), &key, &icmp) is void);
+ assert(search(nums, size(int), &key, &cmp::ints) is void);
};
@test fn sort() void = {
@@ -58,7 +59,7 @@ use types;
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), &icmp);
+ sort(nums, size(int), &cmp::ints);
for (let i = 1z; i < len(nums); i += 1) {
assert(nums[i] >= nums[i - 1]);
};
@@ -67,7 +68,7 @@ use types;
@test fn big_equal() void = {
let nums = alloc([42...], 1000000);
defer free(nums);
- sort(nums, size(int), &icmp);
+ sort(nums, size(int), &cmp::ints);
for (let i = 0z; i < len(nums); i += 1) {
assert(nums[i] == 42);
};
@@ -82,7 +83,7 @@ use types;
nums[i] = random::next(&rand): int;
};
- sort(nums, size(int), &icmp);
+ sort(nums, size(int), &cmp::ints);
for (let i = 1z; i < len(nums); i += 1) {
assert(nums[i] >= nums[i - 1]);
};
@@ -91,17 +92,17 @@ use types;
@test fn sorted() void = {
let nums = [1, 3, 2];
- assert(!sorted(nums, size(int), &icmp));
+ assert(!sorted(nums, size(int), &cmp::ints));
- sort(nums, size(int), &icmp);
- assert(sorted(nums, size(int), &icmp));
- assert(sorted(nums[..0], size(int), &icmp));
+ sort(nums, size(int), &cmp::ints);
+ assert(sorted(nums, size(int), &cmp::ints));
+ assert(sorted(nums[..0], size(int), &cmp::ints));
};
-@test fn icmp() void = {
- assert(icmp(&5, &0) == 1);
- assert(icmp(&0, &5) == -1);
- assert(icmp(&0, &0) == 0);
- assert(icmp(&0, &types::INT_MIN) == 1);
- assert(icmp(&types::INT_MIN, &0) == -1);
+@test fn cmp::ints() void = {
+ assert(cmp::ints(&5, &0) == 1);
+ assert(cmp::ints(&0, &5) == -1);
+ assert(cmp::ints(&0, &0) == 0);
+ assert(cmp::ints(&0, &types::INT_MIN) == 1);
+ assert(cmp::ints(&types::INT_MIN, &0) == -1);
};
diff --git a/sort/cmp/cmp.ha b/sort/cmp/cmp.ha
@@ -0,0 +1,96 @@
+use strings;
+
+// [[sort::cmpfunc]] for use with int.
+export fn ints(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *int), b = *(b: const *int);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with uint.
+export fn uints(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *uint), b = *(b: const *uint);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with i8.
+export fn i8s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *i8), b = *(b: const *i8);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with u8.
+export fn u8s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *u8), b = *(b: const *u8);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with i16.
+export fn i16s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *i16), b = *(b: const *i16);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with u16.
+export fn u16s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *u16), b = *(b: const *u16);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with i32.
+export fn i32s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *i32), b = *(b: const *i32);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with u32.
+export fn u32s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *u32), b = *(b: const *u32);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with i64.
+export fn i64s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *i64), b = *(b: const *i64);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with u64.
+export fn u64s(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *u64), b = *(b: const *u64);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with size.
+export fn sizes(a: const *opaque, b: const *opaque) int = {
+ const a = *(a: const *size), b = *(b: const *size);
+ return if (a < b) -1
+ else if (a > b) 1
+ else 0;
+};
+
+// [[sort::cmpfunc]] for use with str. Sorting is done with respect to Unicode
+// codepoints; see [[strings::compare]].
+export fn strs(a: const *opaque, b: const *opaque) int = {
+ const a = a: const *str, b = b: const *str;
+ return strings::compare(*a, *b);
+};
diff --git a/sort/search.ha b/sort/search.ha
@@ -25,10 +25,3 @@ export fn search(
};
return void;
};
-
-// Performs a binary search over a sorted slice of strings. Sorting is done with
-// respect to Unicode codepoints; see [[strings::compare]]. The index of the
-// matching item in the slice is returned if found, otherwise void is returned.
-export fn searchstrings(in: []const str, key: str) (size | void) = {
- return search(in, size(str), &key, &scmp);
-};
diff --git a/sort/sort.ha b/sort/sort.ha
@@ -19,10 +19,6 @@ export fn sort(items: []opaque, itemsz: size, cmp: *cmpfunc) void = {
powersort(items, itemsz, cmp);
};
-// Sorts a slice of strings in place. Sorting is done with respect to Unicode
-// codepoints; see [[strings::compare]].
-export fn strings(items: []str) void = sort(items, size(str), &scmp);
-
// Checks if all of the items in a slice are sorted.
export fn sorted(items: []opaque, itemsz: size, cmp: *cmpfunc) bool = {
let ba = items: *[*]u8;
@@ -34,10 +30,6 @@ export fn sorted(items: []opaque, itemsz: size, cmp: *cmpfunc) bool = {
return true;
};
-// Checks if all of the strings in a slice are sorted. Order is checked with
-// respect to Unicode codepoints; see [[strings::compare]].
-export fn strings_sorted(items: []str) bool = sorted(items, size(str), &scmp);
-
fn swap(a: *opaque, b: *opaque, sz: size) void = {
let a = a: *[*]u8, b = b: *[*]u8;
for (let i = 0z; i < sz; i += 1) {
diff --git a/sort/types.ha b/sort/types.ha
@@ -1,21 +1,8 @@
// License: MPL-2.0
// (c) 2022 Sebastian <sebastian@sebsite.pw>
-use strings;
// This function type is used when sorting and searching. Given two pointers to
// values, a function of this type should 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.
export type cmpfunc = fn(a: const *opaque, b: const *opaque) int;
-
-fn scmp(a: const *opaque, b: const *opaque) int = {
- const a = a: const *str, b = b: const *str;
- return strings::compare(*a, *b);
-};
-
-fn icmp(a: const *opaque, b: const *opaque) int = {
- const a = *(a: const *int), b = *(b: const *int);
- return if (a < b) -1
- else if (a > b) 1
- else 0;
-};
diff --git a/stdlib.mk b/stdlib.mk
@@ -755,6 +755,13 @@ stdlib_deps_any += $(stdlib_sort_any)
stdlib_sort_linux = $(stdlib_sort_any)
stdlib_sort_freebsd = $(stdlib_sort_any)
+# gen_lib sort::cmp (any)
+stdlib_sort_cmp_any = $(HARECACHE)/sort/cmp/sort_cmp-any.o
+stdlib_env += HARE_TD_sort::cmp=$(HARECACHE)/sort/cmp/sort_cmp.td
+stdlib_deps_any += $(stdlib_sort_cmp_any)
+stdlib_sort_cmp_linux = $(stdlib_sort_cmp_any)
+stdlib_sort_cmp_freebsd = $(stdlib_sort_cmp_any)
+
# gen_lib strconv (any)
stdlib_strconv_any = $(HARECACHE)/strconv/strconv-any.o
stdlib_env += HARE_TD_strconv=$(HARECACHE)/strconv/strconv.td
@@ -1444,7 +1451,7 @@ stdlib_hare_lex_any_srcs = \
$(STDLIB)/hare/lex/token.ha \
$(STDLIB)/hare/lex/lex.ha
-$(HARECACHE)/hare/lex/hare_lex-any.ssa: $(stdlib_hare_lex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
+$(HARECACHE)/hare/lex/hare_lex-any.ssa: $(stdlib_hare_lex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_sort_cmp_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/lex
@$(stdlib_env) $(HAREC) $(HARECFLAGS) -o $@ -Nhare::lex \
@@ -1459,7 +1466,7 @@ stdlib_hare_module_any_srcs = \
$(STDLIB)/hare/module/srcs.ha \
$(STDLIB)/hare/module/util.ha
-$(HARECACHE)/hare/module/hare_module-any.ssa: $(stdlib_hare_module_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_datetime_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM)) $(stdlib_hare_parse_$(PLATFORM)) $(stdlib_hare_unparse_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM)) $(stdlib_time_date_$(PLATFORM)) $(stdlib_types_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM))
+$(HARECACHE)/hare/module/hare_module-any.ssa: $(stdlib_hare_module_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_datetime_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM)) $(stdlib_hare_parse_$(PLATFORM)) $(stdlib_hare_unparse_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM)) $(stdlib_time_date_$(PLATFORM)) $(stdlib_types_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_sort_cmp_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/module
@$(stdlib_env) $(HAREC) $(HARECFLAGS) -o $@ -Nhare::module \
@@ -2064,6 +2071,16 @@ $(HARECACHE)/sort/sort-any.ssa: $(stdlib_sort_any_srcs) $(stdlib_rt) $(stdlib_ma
@$(stdlib_env) $(HAREC) $(HARECFLAGS) -o $@ -Nsort \
-t$(HARECACHE)/sort/sort.td $(stdlib_sort_any_srcs)
+# sort::cmp (+any)
+stdlib_sort_cmp_any_srcs = \
+ $(STDLIB)/sort/cmp/cmp.ha
+
+$(HARECACHE)/sort/cmp/sort_cmp-any.ssa: $(stdlib_sort_cmp_any_srcs) $(stdlib_rt) $(stdlib_strings_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(HARECACHE)/sort/cmp
+ @$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nsort::cmp \
+ -t$(HARECACHE)/sort/cmp/sort_cmp.td $(stdlib_sort_cmp_any_srcs)
+
# strconv (+any)
stdlib_strconv_any_srcs = \
$(STDLIB)/strconv/types.ha \
@@ -3201,6 +3218,13 @@ testlib_deps_any += $(testlib_sort_any)
testlib_sort_linux = $(testlib_sort_any)
testlib_sort_freebsd = $(testlib_sort_any)
+# gen_lib sort::cmp (any)
+testlib_sort_cmp_any = $(TESTCACHE)/sort/cmp/sort_cmp-any.o
+testlib_env += HARE_TD_sort::cmp=$(TESTCACHE)/sort/cmp/sort_cmp.td
+testlib_deps_any += $(testlib_sort_cmp_any)
+testlib_sort_cmp_linux = $(testlib_sort_cmp_any)
+testlib_sort_cmp_freebsd = $(testlib_sort_cmp_any)
+
# gen_lib strconv (any)
testlib_strconv_any = $(TESTCACHE)/strconv/strconv-any.o
testlib_env += HARE_TD_strconv=$(TESTCACHE)/strconv/strconv.td
@@ -3928,7 +3952,7 @@ testlib_hare_lex_any_srcs = \
$(STDLIB)/hare/lex/lex.ha \
$(STDLIB)/hare/lex/+test.ha
-$(TESTCACHE)/hare/lex/hare_lex-any.ssa: $(testlib_hare_lex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_path_$(PLATFORM))
+$(TESTCACHE)/hare/lex/hare_lex-any.ssa: $(testlib_hare_lex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_sort_cmp_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/lex
@$(testlib_env) $(HAREC) $(TESTHARECFLAGS) -o $@ -Nhare::lex \
@@ -3943,7 +3967,7 @@ testlib_hare_module_any_srcs = \
$(STDLIB)/hare/module/srcs.ha \
$(STDLIB)/hare/module/util.ha
-$(TESTCACHE)/hare/module/hare_module-any.ssa: $(testlib_hare_module_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_datetime_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM)) $(testlib_time_date_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
+$(TESTCACHE)/hare/module/hare_module-any.ssa: $(testlib_hare_module_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_datetime_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM)) $(testlib_time_date_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_sort_cmp_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/module
@$(testlib_env) $(HAREC) $(TESTHARECFLAGS) -o $@ -Nhare::module \
@@ -4566,12 +4590,22 @@ testlib_sort_any_srcs = \
$(STDLIB)/sort/types.ha \
$(STDLIB)/sort/+test.ha
-$(TESTCACHE)/sort/sort-any.ssa: $(testlib_sort_any_srcs) $(testlib_rt) $(testlib_math_$(PLATFORM)) $(testlib_math_random_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/sort/sort-any.ssa: $(testlib_sort_any_srcs) $(testlib_rt) $(testlib_math_$(PLATFORM)) $(testlib_math_random_$(PLATFORM)) $(testlib_sort_cmp_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/sort
@$(testlib_env) $(HAREC) $(TESTHARECFLAGS) -o $@ -Nsort \
-t$(TESTCACHE)/sort/sort.td $(testlib_sort_any_srcs)
+# sort::cmp (+any)
+testlib_sort_cmp_any_srcs = \
+ $(STDLIB)/sort/cmp/cmp.ha
+
+$(TESTCACHE)/sort/cmp/sort_cmp-any.ssa: $(testlib_sort_cmp_any_srcs) $(testlib_rt) $(testlib_strings_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(TESTCACHE)/sort/cmp
+ @$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nsort::cmp \
+ -t$(TESTCACHE)/sort/cmp/sort_cmp.td $(testlib_sort_cmp_any_srcs)
+
# strconv (+any)
testlib_strconv_any_srcs = \
$(STDLIB)/strconv/types.ha \