commit 867e92969725196fcc2e1858297a4ac1c88346db
parent c711a0228a96415139eba8e5cdbf9883606f32a6
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sat, 21 Jan 2023 10:09:38 -0500
doc: flesh out an idea about iteration and coroutines
I did try implementing it but took a wrong turn. I still think the idea is good,
but I will try again later.
Diffstat:
1 file changed, 43 insertions(+), 0 deletions(-)
diff --git a/fs/doc/lib/iter.txt b/fs/doc/lib/iter.txt
@@ -0,0 +1,43 @@
+# Iterators
+
+TODO: this isn't implemented yet, only broadly specced out.
+
+Iterators are generic and convenient ways to iterate over arbitrary elements in
+a loop-like syntax. Iterators are coroutines.
+
+Coroutines are two routines that intertwine at the top of RS. Generally,
+routines are called upon, pushing a return address on RS, and then the routine
+finishes, pops return address of RS and jump to that. With coroutine, we don't
+push and pop, we *swap* return addresses on RS until iteration is completed.
+
+An iterator is a word that uses the special "yield" word to perform coroutine
+swapping. Here's an example implementation of the core "begin .. next" loop as
+an iterator:
+
+ 0 value i
+ :iter for ( n -- )
+ to@! i >r begin yield -1 to+ i i not until r> to i ;
+
+ : hello 5 for i . spc> inext ;
+ hello \ prints "5 4 3 2 1 "
+
+Iterators are expected to keep PS and RS balanced between yields. For this
+reason, iteration should be passed through global variables such as "i" in the
+example. To allow iterators to be nested, it's the iterator's responsibility to
+save/restore those variables to RS at iteration intialization/cleanup.
+
+Further examples:
+
+ 0 value i
+ 0 value j
+ :iter for2 ( n max -- )
+ to@! j >r to@! i >r begin yield 1 to+ i i j = until r> to i r> to j ;
+
+ : hello 2 6 for i . spc> inext ;
+ hello \ prints "2 3 4 5 "
+
+ \ "iterinfo" is a structbind to FSInfo
+ : ls p" /" Path :iter iterinfo name stype nl> inext ;
+
+ \ returns size in bytes
+ : totsz 0 p" /" Path :iter iterinfo size + inext ;