duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 37805982e74a5b5ac6eab57e53ac3e6ba027c17b
parent 8cab7ec3b72497e144a588f78d0fa4c58d6f30c2
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu, 23 Feb 2023 10:14:53 -0500

lib/str: add "rfor" iterator

See doc/lib/str. Also, increase RS space for iterator variables to 12 bytes
(add "k"). It was needed for the rfor iterator. I hope I won't have to increase
it by much more.

This was also the first time I used my scheme for "safe bootlo updates on a live
Dusk machine", that is, to "spitBoot" at an alternate location and have the MBR
bootloader optionally boot from that location. It worked well!

Diffstat:
Mfs/doc/iter.txt | 18+++++++++---------
Mfs/doc/lib/str.txt | 9++++++++-
Mfs/lib/str.fs | 17+++++++++++------
Mfs/xcomp/bootlo.fs | 8++++----
4 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/fs/doc/iter.txt b/fs/doc/iter.txt @@ -35,8 +35,8 @@ The heavy lifting is done by ":iterator", which is a does word generating immediate compiling words (in this instance, "for"). When that word is called, a few things happen: -1. 8 bytes are reserved on RS for "i" and "j". It is always 8 bytes for all - iterators, and it's always "i" and "j", even when "j" isn't used. +1. 12 bytes are reserved on RS for "i" and "j". It is always 12 bytes for all + iterators, and it's always "i", "j" and "k", even when they aren't used. 2. A call to "for"'s body is written. 3. Two intertwined ahead jumps are written in a way that allow "unyield" to exit the loop in cases where the iterator has no yield. @@ -44,17 +44,17 @@ few things happen: 5. When "next" (an immediate too) is called, a "yield" is compiled, followed by a backward jump to the beginning of the loop, followed by a forward target for the exit jump compiled at "for". -6. De-allocate the 8 bytes reseved for "i" and "j". +6. De-allocate the 12 bytes reseved for i/j/k. Iterators are expected to keep PS and RS balanced between yields. For this -reason, iteration values should exclusively be passed through "i" and "j". +reason, iteration values should exclusively be passed through i/j/k -## i and j +## i, j and k -"i" and "j" are value-like words (obey "to" semantics) that live on RS. They -work a lot like local variables, but their offset is calculated from RS top -rather than from [rcnt]. "i" lives at RS+4 and "j" lives at RS+8. RS+0 is the -coroutine swapping address. +"i", "j" and "k" are value-like words (obey "to" semantics) that live on RS. +They work a lot like local variables, but their offset is calculated from RS top +rather than from [rcnt]. "i" lives at RS+4, "j" lives at RS+8 and "k" lives at +RS+12. RS+0 is the coroutine swapping address. We use RS for those variables for multiple reasons: diff --git a/fs/doc/lib/str.txt b/fs/doc/lib/str.txt @@ -1,6 +1,7 @@ # String utilities -This unit lives at /lib/str.fs and provides a few string-related words. +This unit lives at /lib/str.fs and provides a few strings an range related +words. Most strings in Dusk are regular strings as doc/usage describes. However, we sometimes have to deal with null-terminated strings and this unit also has words @@ -67,6 +68,12 @@ stringlist ( n "name" "..." -- ) want them in the string) in the quotes. Example: 3 stringlist mylist "foo" "bar" "hello world!" +rfor ( a u -- ) i=a j=idx k=u + An iterator over the range "a u". It iterates "u" time, yielding an increased + "a" as "i". Additionally, an index starting at 0 is maintained at "j". + + Example: S" hello" c@+ rfor i c@ emit j . next --> h0e1l2l3o4 + rtrimright ( n a u -- a u ) Trim "n" characters at the right of range "a u" and return the resulting range. diff --git a/fs/lib/str.fs b/fs/lib/str.fs @@ -14,10 +14,16 @@ create _buf STR_MAXSZ allot : zstrlen ( zstr -- len ) 0 swap $100 [c]? ( idx ) dup 0< if abort" string too long" then ; -: [str]? ( str a u -- idx ) rot> >r >r ( u ) \ V1=aref V2=str - V2 c@ - dup 0>= if V1 swap 1+ for ( a ) - dup V2 c@+ []= if ( a ) V1 - break then 1+ next drop -1 then - else drop -1 then ( idx ) 2rdrop ; +:iterator rfor ( a u -- ) + ?dup if + to k to i 0 to j + begin yield 1 to+ i 1 to+ j j k >= until + else drop then unyield ; + +: [str]? ( str a u -- idx ) rot >r ( a u ) \ V1=str + V1 c@ - dup 0>= if ( a u-adj ) 1+ rfor ( ) + i V1 c@+ []= if j break then next -1 then + else 2drop -1 then ( idx ) rdrop ; : sfind ( str list -- idx ) -1 rot> begin ( idx s a ) rot 1+ rot> ( idx s a ) @@ -43,8 +49,7 @@ create _buf STR_MAXSZ allot next ( c ) drop 0 then rdrop ; : rfind ( a u pairs -- idx ) >r \ V1=pairs - 0 swap for2 ( a ) c@+ V1 rmatch if drop i break then next - ( a ) drop -1 then rdrop ; + rfor ( ) i c@ V1 rmatch if j break then next -1 then rdrop ; create _ 2 c, ," 09" : 0-9? ( c -- f ) _ rmatch ; diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -125,19 +125,19 @@ alias execute | immediate \ Iteration : xtcomp [compile] ] begin word runword compiling not until ; : ivar, ( off -- ) r', _toptr@ execute, ; -: i 4 ivar, ; immediate : j 8 ivar, ; immediate +: i 4 ivar, ; immediate : j 8 ivar, ; immediate : k 12 ivar, ; immediate : :iterator doer immediate xtcomp does> - -8 r+, execute, -4 [rcnt] +! + -12 r+, execute, -4 [rcnt] +! [compile] ahead \ jump to loop [compile] ahead \ exit jump swap [compile] then [compile] begin ( loop ) ; 0 value _breaklbl : next [compile] yield [compile] again [compile] then - 8 r+, 4 [rcnt] +! 0 to@! _breaklbl ?dup drop ; immediate + 12 r+, 4 [rcnt] +! 0 to@! _breaklbl ?dup drop ; immediate CALLSZ CELLSZ + const BRSZ : unyield compile BRSZ 0 r', compile +! ; immediate -: break 12 r+, [compile] ahead to _breaklbl ; immediate +: break 16 r+, [compile] ahead to _breaklbl ; immediate :iterator for ( n -- ) ?dup if to i begin yield -1 to+ i i not until then unyield ;