hare

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

commit 4c62c082965bf14b2931f2e4bb970d03faf25ff3
parent b0e4f055ad2182b44450e5750071cb4d26f9759a
Author: Pierre Curto <pierre.curto@gmail.com>
Date:   Sun,  7 Aug 2022 12:53:19 +0200

strings: update riter and remove push

Remove function pointers and push fields on iterator.
Remove push function.

Fixes: https://todo.sr.ht/~sircmpwn/hare/572

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>

Diffstat:
Mfmt/fmt.ha | 16++++++++--------
Mfnmatch/fnmatch.ha | 4++--
Mhare/module/scan.ha | 2+-
Mstrings/iter.ha | 56+++++++++++++++++++++-----------------------------------
4 files changed, 32 insertions(+), 46 deletions(-)

diff --git a/fmt/fmt.ha b/fmt/fmt.ha @@ -208,11 +208,11 @@ export fn fprintf( }; const idx = if (ascii::isdigit(r)) { - strings::push(&iter, r); + strings::prev(&iter); checkunused = false; yield scan_uint(&iter): size; } else { - strings::push(&iter, r); + strings::prev(&iter); i += 1; yield i - 1; }; @@ -368,7 +368,7 @@ fn scan_uint(iter: *strings::iterator) uint = { if (ascii::isdigit(r)) { append(num, r: u32: u8); } else { - strings::push(iter, r); + strings::prev(iter); match (strconv::stou(strings::fromutf8(num))) { case (strconv::invalid | strconv::overflow) => abort("Invalid format string (invalid index)"); @@ -401,7 +401,7 @@ fn scan_modifier_flags(iter: *strings::iterator, mod: *modifiers) void = { case '+' => flags |= modflags::PLUS; case => - strings::push(iter, r); + strings::prev(iter); break; }; }; @@ -430,7 +430,7 @@ fn scan_modifier_width(iter: *strings::iterator, mod: *modifiers) void = { }; let is_digit = ascii::isdigit(r); - strings::push(iter, r); + strings::prev(iter); if (is_digit) { mod.width = scan_uint(iter); @@ -448,7 +448,7 @@ fn scan_modifier_precision(iter: *strings::iterator, mod: *modifiers) void = { if (r == '.') { mod.precision = scan_uint(iter); } else { - strings::push(iter, r); + strings::prev(iter); }; }; @@ -470,7 +470,7 @@ fn scan_modifier_base(iter: *strings::iterator, mod: *modifiers) void = { case 'b' => mod.base = strconv::base::BIN; case => - strings::push(iter, r); + strings::prev(iter); }; }; @@ -499,7 +499,7 @@ fn scan_parameter_index(iter: *strings::iterator, pi: *paramindex) void = { }; let is_digit = ascii::isdigit(r); - strings::push(iter, r); + strings::prev(iter); if (is_digit) { *pi = scan_uint(iter); } else { diff --git a/fnmatch/fnmatch.ha b/fnmatch/fnmatch.ha @@ -270,7 +270,7 @@ fn match_bracket( let end = advance_or_err(it)?; if (end == ']') { // '-' at the end matches itself - strings::push(it, ']'); + strings::prev(it); last = '-'; found ||= (c == '-'); continue; @@ -290,7 +290,7 @@ fn match_bracket( let t = match_ctype(it, c)?; found ||= t; case => - strings::push(it, next_rune); + strings::prev(it); found ||= (c == '['); }; last = '['; diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -425,7 +425,7 @@ export fn parsetags(in: str) ([]tag | void) = { if (ascii::isalnum(r) || r == '_') { strio::appendrune(&buf, r)!; } else { - strings::push(&iter, r); + strings::prev(&iter); break; }; }; diff --git a/strings/iter.ha b/strings/iter.ha @@ -8,9 +8,7 @@ use encoding::utf8; export type iterator = struct { dec: utf8::decoder, - push: (rune | void), - next: *fn(_: *utf8::decoder) (rune | void | utf8::more | utf8::invalid), - prev: *fn(_: *utf8::decoder) (rune | void | utf8::more | utf8::invalid), + reverse: bool, }; // Initializes a string iterator, starting at the beginning of the string. You @@ -28,21 +26,15 @@ export type iterator = struct { // strings::next(&dup); // void export fn iter(src: str) iterator = iterator { dec = utf8::decode(src), - push = void, - next = &utf8::next, - prev = &utf8::prev, + reverse = false, }; // Initializes a string iterator, starting at the end of the string and moving // backwards with each call to [[next]]. export fn riter(src: str) iterator = { - // TODO: Add rnext et al to avoid blowing up the stack footprint with - // next/prev pointers let ret = iterator { dec = utf8::decode(src), - push = void, - next = &utf8::prev, - prev = &utf8::next, + reverse = true, }; ret.dec.offs = len(src); return ret; @@ -56,13 +48,15 @@ export fn riter(src: str) iterator = { // may cause linguistic errors to arise. To avoid this, you may need to use a // third-party Unicode module instead. export fn next(iter: *iterator) (rune | void) = { - match (iter.push) { - case let r: rune => - iter.push = void; - return r; - case void => void; - }; - return match (iter.next(&iter.dec)) { + if (iter.reverse) { + return next_backward(iter); + } else { + return next_forward(iter); + }; +}; + +fn next_forward(iter: *iterator) (rune | void) = { + return match (utf8::next(&iter.dec)) { case void => void; case (utf8::more | utf8::invalid) => abort("Invalid UTF-8 string (this should not happen)"); @@ -74,8 +68,15 @@ export fn next(iter: *iterator) (rune | void) = { // Get the previous rune from an iterator, or void when at the start of the // string. export fn prev(iter: *iterator) (rune | void) = { - assert(iter.push is void); - return match (iter.prev(&iter.dec)) { + if (iter.reverse) { + return next_forward(iter); + } else { + return next_backward(iter); + }; +}; + +fn next_backward(iter: *iterator) (rune | void) = { + return match (utf8::prev(&iter.dec)) { case void => yield void; case (utf8::more | utf8::invalid) => @@ -85,21 +86,8 @@ export fn prev(iter: *iterator) (rune | void) = { }; }; -// Causes the next call to [[next]] to return the provided rune, effectively -// un-reading it. The next call using this iterator *must* be [[next]]; all other -// functions will cause the program to abort until the pushed rune is consumed. -// This does not modify the underlying string, and as such, subsequent calls to -// functions like [[prev]] or [[iterstr]] will behave as if push were never called. -export fn push(iter: *iterator, r: rune) void = { - // TODO: This should probably be removed, and the push field removed - // from the struct. - assert(iter.push is void); - iter.push = r; -}; - // Return a substring from the next rune to the end of the string. export fn iterstr(iter: *iterator) str = { - assert(iter.push is void); return fromutf8(iter.dec.src[iter.dec.offs..]); }; @@ -128,8 +116,6 @@ export fn iterstr(iter: *iterator) str = { }; assert(next(&s) is void); assert(next(&s) is void); - push(&s, 'q'); - assert(next(&s) as rune == 'q'); assert(prev(&s) as rune == 'は'); s = riter("にちは");