duskos

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

commit bc19febc3f82b34e46a68831fdf4bc19d5cdb9ce
parent 9d3056effbcccbc4e4db16d1b26eb7068b3e2c47
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri, 30 Dec 2022 10:48:44 -0500

doc/usage: add missing section about control flow

I hadn't realized it wasn't there. Big gap in docs!

Diffstat:
Mfs/doc/usage.txt | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfs/xcomp/bootlo.fs | 11-----------
2 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/fs/doc/usage.txt b/fs/doc/usage.txt @@ -49,6 +49,82 @@ character: Any other character following the '\' results in that character being parsed as- is, the preceding '\' being ignored. +## Control flow + +: foo if 42 else 54 then . ; + +0 foo --> prints 54 +1 foo --> prints 42 + +: foo begin dup . 1- ?dup not until ; + +5 foo --> prints 54321 + +: foo begin 'X' emit again ; + +foo --> prints X forever + +: foo begin ?dup while 1- dup . repeat ; + +5 foo --> prints 43210 + +A begin..repeat loop can have more than 1 while. In that case, things get weird +and it behaves like "if", that is that each while has its own "loop exit point". +Weird, but sometimes useful. + +: foo begin + dup 10 <> while dup 15 <> while dup . 1+ repeat + ( second while exit point ) .x1 else + ( first while exit point ) . then ; + +5 foo --> prints 5678910 +11 foo --> prints 111213140f + +Dusk has no do..loop. Instead, it has begin..next. "next" decreases RS top and, +if zero, pops it and stops the loop. Otherwise, branches to begin. "begin" +doesn't automatically puts anything on RS. This has to be done with ">r". + +: foo >r begin r@ . next ; + +5 foo --> prints 54321 + +The "case" structure allows us to "fan out" to many possible branches depending +on a single value. It's the functional equivalent of nested "if..then", but +more readable. The idea is that "case" pushes a value from PS to RS, and then +each "of" evaluates that value with a "truth word". + +The part before each "of" is executed as-is and then "of" does a "r@" and +executes the specified word. If the word yields nonzero, then we stay in that +branch. Otherwise, we branch to "endof". + +During the execution of a branch, the value in question is still available +through "r@". Then, upon reaching "endof", we branch to "endcase" which then +drops that value from RS. + +If no case matches, the part between the last "endof" and the "endcase" is +executed. The value in question is also available through "r@". + +: foo case + 5 of = ." I am 5!" endof + of 0< ." I am negative!" endof + 100 of < ." I am higher than 100" endof \ yeah, order is counter-intuitive... + r@ .f" This number, %d, is something else" endcase ; + +5 foo --> I am 5! +-1 foo --> I am negative! +101 foo --> I am higher than 100 +42 foo --> This number, 42, is something else + +None of these control structures above can be ran in interpret mode. They only +work when compiled. Sometimes, a little conditional in interpret mode can be +useful. + +42 [if] ." this will be executed" [then] +0 [if] ." this won't" even if the code is nonsensical [then] + +[if]..[then] work like comments and simply drop words until "[then]". There is +no "[else]". + ## Values, cells, constants, aliases A "cell" is a word that refers to an area in memory. Calling this word yields diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -131,20 +131,9 @@ alias noop idle begin dup 8b to@+ V2 = if leave then next ( c ) V2 1- c@ = if r> 1- r> - ( i ) else rdrop rdrop -1 then ; -\ while..repeat : while [compile] if swap ; immediate : repeat [compile] again [compile] then ; immediate -\ case..endcase -\ The case statement is very similar to what we see in other forths, but with -\ one major difference: the "of" word specifies the truth word. So, the -\ "of" we see in other forths is equivalent to "of =" in Dusk OS. The comparator -\ has to be a single word following "of". -\ case x of = ... endof y of < ... endof ... endcase -\ is syntactic sugar for: -\ >r x r@ = if ... else y r@ < if ... else ... then then rdrop -\ NOTE: if you want to access your reference value in the final "else", you -\ need to use "r@". : case ( -- then-stopgap ) 0 [compile] >r ; immediate : of ( -- jump-addr ) [compile] r@ word compword [compile] if ; immediate : endof [compile] else ; immediate