6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 9:46 am

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Re: The coolest words
PostPosted: Tue Mar 23, 2021 7:51 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
GARTHWILSON wrote:

The CO word above defined as a secondary would have very limited usefulness if any though, because your return address gets changed. I have RSWAP defined in my '816 Forth as:
Code:
       HEADER "RSWAP", NOT_IMMEDIATE   ; Swaps the two top return-stack cells.
RSWAP: PRIMITIVE
       LDA   1,S
       STA   N
       LDA   3,S
       STA   1,S
       LDA   N
       STA   3,S
       GO_NEXT
 ;-------------------
which executes much, much faster and doesn't mess up where it comes back to for the next instruction.


The purpose of CO is to swap the return addresses. It's a co-routine word. If I had RSWAP in my system, I would define CO like this:
Code:
: CO
   RSWAP ;

If I wanted to make CO a primitive, since Fleet Forth is an ITC Forth, I would have to write it to swap the top of the return stack with IP.
Here are two words used for a trivial example:
Code:
: COROUTINE1
   BEGIN
      CR ." ROUTINE ONE HERE!"
      CO DONE?
   UNTIL ;
: COROUTINE2
   BEGIN
      CR ." SECOND COROUTINE!"
      CO DONE?
   UNTIL ;

And a portion of the system log showing their execution:
Code:
' COROUTINE1 >BODY >R COROUTINE2
SECOND COROUTINE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!

or they can be launched another way:
Code:
: ROUTINES
   COROUTINE1  COROUTINE2 ;

And a sample run:
Code:
ROUTINES
ROUTINE ONE HERE!
SECOND COROUTINE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!
SECOND COROUTINE!
ROUTINE ONE HERE!

A trivial example to be sure.
Here is something useful. Fleet Forth has the word RB ( restore base ). Among other places, it is used in the definition of NUMBER? .
Code:
: RB  ( -- )
   BASE @ R> 2>R  CO
   R> BASE ! ;

The behavior of a word like RB is fairly straight forward. perform the part before CO right now. Perform the part after CO when this word's caller exits.
Here is a walkthrough of how RB works:
Code:
   BASE @ R> 2>R

The value in BASE is fetched then the return address of RB's caller is moved from the return stack to the data stack. Since 2>R preserves the order of the values moved to the return stack, after 2>R executes, the value of BASE will be tucked under the return address of RB's caller on the return stack.
Code:
: CO   2R> SWAP 2>R ;

When at the start of CO , there are three values of immediate interest on the return stack. The value of BASE , the return address of RB's caller, and the return address of RB .
Code:
   2R> SWAP 2>R ;

CO swaps the two return addresses. When CO exits, it exits into RB's caller at the point just after RB .

When RB's caller finishes and exits, it exits into RB just after CO .
Code:
   R> BASE ! ;

The original value of BASE saved to the return stack by RB is now the top value of the return stack. It is pulled off the return stack and stored back in BASE . RB exits into the word that called RB's caller.

Another useful place for CO is in the definition of WITH-WORDS , a handy utility word in Fleet Forth.
WITH-WORDS works like this:
Code:
: NAMEX  <DO THIS ONCE> WITH-WORDS <DO THIS ONCE FOR EACH WORD IN THE CONTEXT VOCABULARY> ;

The thread of Forth after WITH-WORDS gets executed once for each word in the context vocabulary. The only values on the data stack when that thread executes are whatever was on the data stack prior to the execution of WITH-WORDS and the NFA of the word for which this thread is executed.


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Thu Mar 25, 2021 5:51 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
JimBoyd wrote:
Here is something useful. Fleet Forth has the word RB ( restore base ). Among other places, it is used in the definition of NUMBER? .
Code:
: RB  ( -- )
   BASE @ R> 2>R  CO
   R> BASE ! ;

The behavior of a word like RB is fairly straight forward. perform the part before CO right now. Perform the part after CO when this word's caller exits.

That's too cool for school!

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Sun Apr 11, 2021 6:23 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
I think RB and CO are my two new favorite words.
I've always saved and restored the base myself in words that needed to change it, but that solution is a lot more elegant. I especially enjoy how simple both words are. RB is also, by far, the most practical use of co-routines I have seen.


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Sat May 01, 2021 1:22 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895

I cover coroutines in greater depth here.


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Sat May 01, 2021 1:29 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895

I tested CO and RB on Durex Forth for the C64. Durex Forth is an STC Forth. Both words needed a slight redefinition because Durex Forth didn't have 2>R and 2R> .
Code:
: CO   R> R> SWAP >R >R ;
: RB   R> BASE @ >R >R  CO  R> BASE ! ;

These and the GREET HELLO examples worked as expected.


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Wed Aug 28, 2024 11:40 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
CO in my Forth has been a primitive for some time. Here is an excerpt from my Forth kernel's source. It was built with a metacompiler.
The three sections of code below are presented in the reverse order they appear in the kernel source. I felt this would make the source for CO easier to follow.
Code:
CODE CO  (  R: ADR1 -- ADR2 )
         ( IP: ADR2 -- ADR1 )
   PLA  TAY  PLA
   (CO) JMP  END-CODE

   LABEL (CO)    ( IN THE BODY OF >FORTH)
   N STA
   IP 1+ LDA  PHA
   IP    LDA  PHA
   N LDA  IP STY
   ' EXIT @ 4 + JMP  ( THIS JMP)

   ( JUMPS HERE)
   IP 1+ STA
   ( FALLS INTO NEXT)

The following hand translation is provided for those not familiar or comfortable with RPN assembly.
Code:
CODE CO  (  R: ADR1 -- ADR2 )
         ( IP: ADR2 -- ADR1 )
   PLA
   TAY
   PLA
   JMP (CO)
   END-CODE

   LABEL (CO)    ( IN THE BODY OF >FORTH)
   STA N
   LDA IP+1
   PHA
   LDA IP
   PHA
   LDA N
   STY IP
   JMP EXIT4   ( THIS JMP)

   ( JUMPS HERE)
   LABEL EXIT4
   STA IP+1
   ( FALLS INTO NEXT)

As I mentioned previously, CO swaps IP with the top of the return stack.
By taking advantage of what was already in another primitive, the SUBRoutine >FORTH , the primitive version of CO is smaller than the high level version.


Top
 Profile  
Reply with quote  
 Post subject: Re: The coolest words
PostPosted: Thu Aug 29, 2024 12:05 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
In my humble opinion, another cool word is FH , from here, in Leo Brodie's "Thinking Forth."
Code:
: FH  \  ( offset -- offset-block )  "from here" 
   BLK @  ?DUP 0= IF  SCR @  THEN  + ;

When used in a block which is loading, FH will add the block number in BLK to the number on the data stack. This allows relative loading.
Here is an example from my system loader.
Code:
SCR# 2
// LOAD BLOCK
DECIMAL
CR .( DONE?      )         2 FH LOAD
CR .( THRU --> <-- ;S )    3 FH LOAD
CR .( ASSEMBLER  )   4 FH 16 FH THRU
CR .( UTILITIES  )  17 FH 25 FH THRU
CR .( SF EDITOR  )  26 FH 38 FH THRU
CR .( SCREEN ED  )        39 FH LOAD
CR .( AUX STACK  )  45 FH 48 FH THRU
CR .( MORE UTILITIES AND EXTENSIONS)
CR                  49 FH 80 FH THRU
CR .( VIRTUAL MEM ) 81 FH 86 FH THRU
CR .( CONDITIONAL COMP )  91 FH LOAD
CR .( AFIND       ) 92 FH 93 FH THRU
CR .( FILES (ERR)   94 FH 95 FH THRU
CR .( MULTITASKER) 96 FH 100 FH THRU

This screen of source is on block 2. When the phrase 2 FH LOAD is interpreted, the screen on block 4 is loaded.
When not loading (BLK is zero), FH adds the screen number in SCR to the number on the stack. When editing this same screen on block 2, typing 3 FH LIST will list the screen with the source for THRU , --> , <-- and ;S on block 5.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 20 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: