I moved
CO ( coroutine) and
RB ( restore base) from the system loader to the kernel.
CO is a word that allows two words to be coroutines and
RB used in a word causes the base to be restored, when the word exits, to what it was prior to the execution of
RB .
My preference is that words, like
DUMP and
SEE , do not alter
BASE. If I want to
SEE in hexadecimal I'll say
HEX SEE <SOME.WORD> . If I want a decimal dump I'll say
DECIMAL <some address> <some count> DUMP . There are certain situations where this doesn't work. When communicating with a Commodore disk drive over the command channel, the command is a text string including the numbers for disk ( 0 or 1), track, and sector. In the Fleet Forth kernel, I use some of the pictured numeric words to build a text string, but
BASE has to be decimal. By moving
RB to the kernel, I can start the word with
RB DECIMAL .
Having
RB in the kernel necessitated the inclusion of
CO . Here are their definitions.
Code:
SCR# 9C
// CO RB
HEX
// COROUTINES
: CO 2R> SWAP 2>R ;
// RESTORE BASE AT END OF WORD
// CALLING RB
: RB ( -- )
BASE @ R> 2>R CO
R> BASE ! ;
A note about
2>R ( and
2R> ), When moving two cells ( four bytes in this case ) from one stack to the other, the byte order is preserved. When two cells are moved from the data stack, as in this case, the value that was on top of the data stack will be the one that is on top of the return stack. As an example,
CO could have been defined as:
Code:
: CO 2R> >R >R ;
or
Code:
: CO R> R> 2>R ;
For the newcomers to Forth, I will attempt an explanation of how
RB works.
Get the value of
BASE.
Pull the return address off the return stack ( the return point in the calling word.)
Move both to the return stack with the value of
BASE tucked under the return address of the calling word.
CO is executed which places
IP on the stack.
CO switches the two addresses and returns to the word that called
RB .
When that word
EXITs,
RB resumes execution at the point after
CO.
The previous value of
BASE is still on the return stack and is transfered to the data stack and stored in
BASE.
I don't remember where I saw
CO , but I knew it would be useful. The other place it is used is in the definition of
WITH-WORDS .
Code:
SCR# 38
// WITH-WORDS WORDS
HEX
: WITH-WORDS ( -- NFA )
COLS ?CR
R> CONTEXT @
BEGIN
@ DUP DONE? 0= AND
WHILE
2DUP 2>R L>NAME
SWAP >R CO 2R>
REPEAT
2DROP ;
Here is an example of its use in
WORDSCode:
: WORDS ( -- )
WITH-WORDS DUP C@ 1F AND 1+ ?CR
ID. TAB ;
For each word in the
CONTEXT VOCABULARY , the code following
WITH-WORDS through the
EXIT compiled by semicolon is executed with the address of the word's name field on the data stack.