Revised 2014-03-10
Background
The "control-flow stack" in Forth-94 describes the
compile-time behaviour of control structures. Support functions
for the
control-flow stack include AHEAD CS-ROLL
CS-PICK . Using these tools it is possible to create
conditionals and
control structures such as WHILE REPEAT
ELSE CASE in a portable manner.
Despite the potential the control-flow stack offers, the tools
provided by Forth-94 are few with the result only simple
control structures can be realized. To address this shortcoming
the following extensions are presented.
Implementing the extensions requires knowledge of the host system. A sample implementation is provided.
Control-Flow Stack Extensions
Examples
1. BEGINCASE..NEXTCASE \ BEGINCASE..NEXTCASE \ MPE CASE extension : BEGINCASE postpone case postpone begin cs-push ; immediate : NEXT-CASE cs-pop postpone again postpone endcase ; immediate : NEXTCASE postpone drop postpone next-case ; immediate : test begincase cr ." Press a key ('2' '4' '9' exits) : " key [char] 2 of ." ... 2 " endof [char] 4 of ." ... 4 " endof [char] 9 of ." ... 9 " endof dup emit ." try again" nextcase ;
2. "Miser's CASE" \ Wil Baden's COND THENS : COND cs-mark ; immediate : THENS begin cs-test while postpone then repeat cs-drop ; immediate : OF postpone over postpone = postpone if postpone drop ; immediate \ Add Pascal-like features : WHEN postpone else cs-push postpone thens cs-pop postpone drop ; immediate : EQUAL postpone over postpone - postpone if ; immediate : (range) \ assumes 2's complement arithmetic 2>r dup 2r> over - -rot - u< ; : RANGE \ values may be signed or unsigned postpone (range) postpone if ; immediate \ Add C Switch flow-through : CONTINUE cs-push postpone thens cs-mark cs-pop ; immediate \ Forth-94 compatibility words : CASE postpone cond ; immediate : ENDOF postpone else ; immediate : ENDCASE postpone drop postpone thens ; immediate \ Case demo hex : test ( n ) space cond cond 0 1F range 7F equal when ." Control char " else cond 20 2F range 3A 40 range 5B 60 range 7B 7E range when ." Punctuation " else cond 30 39 range when ." Digit " else cond 41 5A range when ." Upper case letter " else cond 61 7A range when ." Lower case letter " else drop ." Not a character " thens ; decimal cr cr .( [press any key] ) key drop cr cr .( Miser's CASE demo ...) cr cr char a .( ) dup emit test cr char , .( ) dup emit test cr char 8 .( ) dup emit test cr char ? .( ) dup emit test cr char K .( ) dup emit test cr 0 dup 3 .r test cr 127 dup 3 .r test cr 128 dup 3 .r test
3. "Duff's Device"
\ Requires "Miser's CASE" \ : send >r >r dup c@ r@ c! char+ r> r> ; : send >r >r dup c@ emit char+ r> r> ; : duff ( data port count ) dup 7 + 8 / swap 8 mod case 0 of begin [ cs-push ] send endof 7 of continue send endof 6 of continue send endof 5 of continue send endof 4 of continue send endof 3 of continue send endof 2 of continue send endof 1 of continue send 1- dup 0= [ cs-pop ] until endof endcase drop 2drop ; : filldata ( ) 26 0 do i [char] A + pad i chars + c! loop ; : go ( ) filldata 27 1 do cr pad 0 i dup . duff 3 +loop ; cr cr .( [press any key] ) key drop cr cr .( Duff's Device demo ...) cr go
4. BEGIN..REPEAT with optional WHILE \ BEGIN..REPEAT with optional WHILE \ For demonstration purposes only. : back \ alias for AGAIN or 0 UNTIL [defined] again [if] postpone again [else] postpone 0 postpone until [then] ; immediate \ drop marker : -mark ( C: mark -- ; orig|dest -- orig|dest ) cs-test 0= if cs-drop then ; : BEGIN ( C: -- mark dest ) cs-mark postpone begin ; immediate : WHILE cs-push -mark cs-pop postpone while ; immediate : REPEAT postpone back cs-test if postpone then else -mark then ; immediate : UNTIL postpone until -mark ; immediate \ Not needed since BEGIN..REPEAT now replaces AGAIN \ : AGAIN postpone back ; immediate \ Compilation tests \ Forth-94 loops : t1 begin 0 while repeat ; : t2 begin 0 while 1 while repeat then ; : t3 begin 1 until ; : t4 begin 1 while 1 until then ; : t5 begin 0 while begin 1 while repeat repeat ; \ Infinite loop using BEGIN..REPEAT : ?break key? if key drop quit then ; : t6 begin ?break repeat ; : t7 begin ?break t5 repeat ;
\ Control-flow stack extension words. Sample implementation. \ Assumes control flow is on the data stack and control flow \ items are one cell wide. variable cf0 \ initialize control flow stack base : !cfs ( -- ) sp@ cf0 ! ; !cfs : #cs ( -- n ) sp@ cf0 @ - negate [ 1 cells ] literal / 1- 0 max ( handle empty stack) ; : CS-PICK pick ( +bal) ; : CS-ROLL roll ; : CS-DROP drop ( -bal) ; : CS-MARK 0 ( +bal) ; : CS-TEST dup 0<> ; : CS-PUSH #cs -roll ; : CS-POP #cs roll ; : : ( "name" -- ) ... ( !csp bal off) !cfs ; : :NONAME ( -- xt ) ... ( xt ) ( !csp bal off) !cfs ; \ start Forth with control flow base set to a safe value : COLD ( -- ) ... !cfs ;
2014-03-10 Update example 2. Add sample implementation.
Page updated: 10 Mar 2014