hare

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

commit c3d027a2768f46652c6282287970e99c20ca5c4e
parent a8d9063e6095ddad0d5083647f70a614b46189fd
Author: Bor Grošelj Simić <bgs@turminal.net>
Date:   Wed, 26 Apr 2023 11:51:10 +0200

fnmatch: simplify and modernize

This module was written a while ago and idiomatic hare has changed
since. Also noticed some things could be simplified while doing so.

Diffstat:
Mfnmatch/fnmatch.ha | 63+++++++++++++++++++--------------------------------------------
1 file changed, 19 insertions(+), 44 deletions(-)

diff --git a/fnmatch/fnmatch.ha b/fnmatch/fnmatch.ha @@ -8,7 +8,6 @@ use ascii; use errors; use strings; -use sort; // A set of flags that alter the matching behavior of [[fnmatch]] export type flags = enum uint { @@ -53,21 +52,12 @@ export fn fnmatch(pattern: str, string: str, flag: flags...) bool = { for (let i = 0z; i < len(flag); i += 1) { fl |= flag[i]; }; - if (fl & flags::PATHNAME != 0) { - match (fnmatch_pathname(pattern, string, fl)) { - case let b: bool => - return b; - case => - return false; - }; + let b = if (fl & flags::PATHNAME != 0) { + yield fnmatch_pathname(pattern, string, fl); } else { - match (fnmatch_internal(pattern, string, fl)) { - case let b: bool => - return b; - case => - return false; - }; + yield fnmatch_internal(pattern, string, fl); }; + return b is bool && b: bool; }; // Split the pattern and the string on every '/' and process each part @@ -262,6 +252,7 @@ fn match_bracket( if (first == ']') { first = advance_or_err(it)?; }; + for (let r = first; true; r = advance_or_err(it)?) { switch (r) { case ']' => @@ -275,12 +266,13 @@ fn match_bracket( found ||= (c == '-'); continue; }; - if (last is void) { + match (last) { + case void => return errors::invalid; + case let l: rune => + found ||= (l: u32 <= c: u32 && c: u32 <= end: u32); + last = void; // forbid 'a-f-n' }; - let l = last: rune; - found ||= (l: u32 <= c: u32 && c: u32 <= end: u32); - last = void; // forbid 'a-f-n' case '[' => let next_rune = advance_or_err(it)?; switch (next_rune) { // TODO localization @@ -301,12 +293,9 @@ fn match_bracket( }; let cnt = len(strings::iterstr(&old)) - len(strings::iterstr(it)); - if (last is rune && first == last: rune && cnt >= 4) { - switch (first) { - case '=', '.', ':' => - return errors::invalid; - case => void; - }; + if (last is rune && first == last: rune && cnt >= 4 + && (first == '=' || first == '.' || first == ':')) { + return errors::invalid; }; return found ^^ inv; }; @@ -324,21 +313,7 @@ fn match_ctype(it: *strings::iterator, c: rune) (bool | errors::invalid) = { return errors::invalid; }; let name = strings::sub(s, 0, i - 1); - match (ctype_name_to_func(name)) { - case null => - return errors::invalid; - case let f: *fn(c: rune) bool => - return f(c); - }; -}; - -type funcmap = (str, *fn(c: rune) bool); - -fn cmp(a: const *void, b: const *void) int = - strings::compare((a: *funcmap).0, *(b: const *str)); - -fn ctype_name_to_func(name: str) nullable *fn(c: rune) bool = { - const map: [_]funcmap = [ + const map: [_](str, *fn(_: rune) bool) = [ ("alnum", &ascii::isalnum), ("alpha", &ascii::isalpha), ("blank", &ascii::isblank), ("cntrl", &ascii::iscntrl), ("digit", &ascii::isdigit), ("graph", &ascii::isgraph), @@ -346,12 +321,12 @@ fn ctype_name_to_func(name: str) nullable *fn(c: rune) bool = { ("punct", &ascii::ispunct), ("space", &ascii::isspace), ("upper", &ascii::isupper), ("xdigit",&ascii::isxdigit), ]; - match (sort::search(map, size(funcmap), &name, &cmp)) { - case void => - return null: nullable *fn(c: rune) bool; - case let ind: size => - return map[ind].1; + for (let i = 0z; i < len(map); i += 1) { + if (map[i].0 == name) { + return map[i].1(c); + }; }; + return errors::invalid; }; fn pat_next(pat: *strings::iterator, fl: flags) (token | errors::invalid) = {