hare

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

commit 911ecbd8f2e4f577b5bc542460e8fcd291ceeade
parent e6cab9bc88bdc902fc43a3526bd8bc8d2e39e442
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sat,  2 Apr 2022 00:05:26 -0400

sort: add strings and sortstrings

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mhare/lex/lex.ha | 18+++++-------------
Mhare/module/scan.ha | 10++--------
Msort/search.ha | 13+++++++++++++
Msort/sort.ha | 4++++
4 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha @@ -149,11 +149,6 @@ export fn lex(lex: *lexer) (token | error) = { fn is_name(r: rune, num: bool) bool = ascii::isalpha(r) || r == '_' || r == '@' || (num && ascii::isdigit(r)); -fn ncmp(a: const *void, b: const *void) int = { - let a = a: const *str, b = b: const *str; - return strings::strcmp(*a, *b); -}; - fn lex_unicode(lex: *lexer, loc: location, n: size) (rune | error) = { assert(n < 9); let buf: [8]u8 = [0...]; @@ -312,15 +307,12 @@ fn lex_name(lex: *lexer, loc: location, label: bool) (token | error) = { return (ltok::LABEL, n, loc); }; - match (sort::search(bmap[..ltok::LAST_KEYWORD+1], - size(str), &n, &ncmp)) { - case null => + match (sort::searchstrings(bmap[..ltok::LAST_KEYWORD+1], n)) { + case void => return (ltok::NAME, n, loc); - case let v: *void => - defer free(n); - let tok = v: uintptr - &bmap[0]: uintptr; - tok /= size(str): uintptr; - return (tok: ltok, void, loc); + case let i: size => + free(n); + return (i: ltok, void, loc); }; }; diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -120,12 +120,6 @@ export fn parse_name(name: str) (str, str, []tag) = { return (base, ext, tags); }; -fn strcmp(a: const *void, b: const *void) int = { - const a = *(a: const *str); - const b = *(b: const *str); - return ascii::strcmp(a, b) as int; -}; - fn scan_directory( ctx: *context, ver: *version, @@ -180,8 +174,8 @@ fn scan_directory( }; // Sorted to keep the hash consistent - sort::sort(dirs, size(str), &strcmp); - sort::sort(files, size(str), &strcmp); + sort::strings(dirs); + sort::strings(files); // Tuple of is_directory, basename, tags, and path to a candidate input. let inputs: [](bool, str, []tag, str) = []; diff --git a/sort/search.ha b/sort/search.ha @@ -24,3 +24,16 @@ export fn search( }; return null; }; + +// Performs a binary search over a sorted slice of strings. Sorting is done with +// respect to Unicode codepoints; see [[strings::strcmp]]. 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) = { + match (search(in, size(str), &key, &scmp)) { + case null => + return void; + case let v: *const void => + const offs = (v: uintptr - in: *[*]const str: uintptr); + return (offs / size(str): uintptr): size; + }; +}; diff --git a/sort/sort.ha b/sort/sort.ha @@ -16,6 +16,10 @@ export fn sort(items: []void, itemsz: size, cmp: *cmpfunc) void = { insort(items, itemsz, cmp); }; +// Sorts a slice of strings in place. Sorting is done with respect to Unicode +// codepoints; see [[strings::strcmp]]. +export fn strings(items: []str) void = sort(items, size(str), &scmp); + fn swap(a: *void, b: *void, sz: size) void = { let a = a: *[*]u8, b = b: *[*]u8; for (let i = 0z; i < sz; i += 1) {