6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 9:54 pm

All times are UTC




Post new topic Reply to topic  [ 63 posts ]  Go to page Previous  1, 2, 3, 4, 5
Author Message
PostPosted: Sun Oct 15, 2023 9:43 pm 
Offline

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

As promised, here is what GEN does.
I already said GEN was a generator. Given an input of N, it will return the numbers from 0 to N-1; however, the way GEN does this is by placing a number on the data stack and executing the Forth threaded code fragment following GEN in the word where it appears. It runs this threaded code fragment once for each number it returns.
Two more words from M. L. Gassanenko are used in the definition of GEN , the pair PRO and CONT .
Code:
: PRO  ( -- )
   R> R> >L  ENTER  L> DROP ;
: CONT  ( -- )
   L> >R R@ ENTER R> >L ;

M. L. Gassanenko refers to PRO as a prolog-like procedure prologue.
I've previously shown ENTER in this thread; nonetheless, here is the source for ENTER .
Code:
: ENTER  ( T-ADR -- )  >R ;

ENTER takes the address of a fragment of threaded code and runs the threaded code fragment at that address. When that threaded code fragment exits, control is returned to the fragment which executed ENTER .
>L and L> are words to move a number to and from what M. L. Gassanenko refers to as a continuation stack.
Here is the source for GEN .
Code:
: GEN  ( U1 -- U2 )
   PRO  0 ?DO  I CONT  LOOP ;

And the source for TEST .
Code:
: TEST
   5 GEN . ;

PRO pulls two addresses off the return stack. The second address, in this case an address in the body of TEST, is placed on the continuation stack. The first address pulled from the return stack, an address in the body of GEN , is used as a parameter for ENTER to transfer control back to GEN . Control is returned back to PRO when GEN exits. PRO removes and drops the address it previously placed on the continuation stack then exits, transferring control back to the word which called TEST .
In the word GEN , CONT pulls the address off the continuation stack. This address is in TEST just past GEN . It saves a copy of this address on the return stack and transfers control to that portion of TEST which is after GEN . Control is returned to CONT when TEST exits. CONT moves that address from the return stack back to the continuation stack. The threaded code after GEN in the word TEST will run for each number returned by GEN .

Back to the brain teaser.
Code:
: GENTEST  ( -- )
   2 GEN CR .
   4 GEN CR 2 .R
   3 GEN CR 3 .R ;

The first occurrence of GEN will return two numbers. It will cause this fragment of Forth to run for each of them.
Code:
         CR .
   4 GEN CR 2 .R
   3 GEN CR 3 .R ;

Each time it runs the next occurrence of GEN will cause this fragment of Forth to run four times.
Code:
         CR 2 .R
   3 GEN CR 3 .R ;

Each time this fragment runs the last occurrence of GEN will cause this final fragment of Forth from the word GENTEST to run three times.
Code:
         CR 3 .R ;

That last fragment runs a total of 24 times each time GENTEST is run.

Words which manipulate return addresses are notoriously difficult to use in a definite loop, where the parameters are kept on the return stack. The pair of words PRO and CONT get around this. PRO gets to the addresses it needs because it is used before any words which place data on the return stack. CONT can get to the address it needs because it is no longer on the return stack.

M. L. Gassanenko gives the example of the word STACK , which non-destructively returns the numbers on the data stack similar to how GEN returns a range of numbers. Many Forth systems have the word .S to non-destructively display the contents of the data stack; however, the stack contents could be displayed as signed or unsigned numbers. This version shows the stack contents as signed numbers:
Code:
: .S   STACK . ;

while this version shows the stack contents as unsigned numbers:
Code:
: U.S   STACK U. ;


My Forth has an auxiliary stack. I defined the continuation stack words >L and L> as aliases for the auxiliary stack words.
Code:
: >L   >A ;
: L>   A> ;

In the word CONT
Code:
   L> >R R@

is functionally equivalent to
Code:
   L> DUP >R

or on my system
Code:
   L> DUP>R

so I redefined CONT
Code:
: CONT
   L> DUP>R ENTER R> >L ;

I wondered why CONT was defined this way and not simply:
Code:
: CONT
   L@ ENTER ;

At first I thought CONT removed the address from the continuation stack to permit something like the word GEN2 .
Code:
: GEN  ( U -- )
   PRO  0 ?DO  I CONT  LOOP ;
: GEN2  ( U -- )
   PRO  GEN  0 ?DO  I CONT  LOOP ;

However, a word like GEN2 could be defined like this:
Code:
: GEN2  ( U -- )
   GEN  PRO  0 ?DO  I CONT  LOOP ;

A word like GEN2 is not even necessary.
Code:
: TESTA  ( U -- )
   GEN GEN . ;
: TESTB  ( U -- )
   GEN2 . ;

So, why the lengthier definition for CONT ? Any thoughts on this?


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 17, 2023 5:34 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8428
Location: Southern California
JimBoyd wrote:
ENTER takes the address of a fragment of threaded code and runs the threaded code fragment at that address. When that threaded code fragment exits, control is returned to the fragment which executed ENTER .

I can't take the time to understand everything above, but this part looks neat, allowing you to enter a word somewhere other than at the beginning, something I've kind of wanted at times, like this:
Code:
: SOME_WORD
   do_stuff
   BEGIN
       do_more_stuff
       yada-yada       <---Optionally enter here
       Condition?
   UNTIL
   etc.             ;

You'd have to use [ here ] (and maybe store it before the ] ) so you'd have the address of where to enter.  Hopefully I'm understanding it right.  Chalk up another one for Forth's unexpected flexibility.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 26, 2023 9:09 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 851
GARTHWILSON wrote:
JimBoyd wrote:
ENTER takes the address of a fragment of threaded code and runs the threaded code fragment at that address. When that threaded code fragment exits, control is returned to the fragment which executed ENTER .

I can't take the time to understand everything above, but this part looks neat, allowing you to enter a word somewhere other than at the beginning, something I've kind of wanted at times, like this:
Code:
: SOME_WORD
   do_stuff
   BEGIN
       do_more_stuff
       yada-yada       <---Optionally enter here
       Condition?
   UNTIL
   etc.             ;

You'd have to use [ here ] (and maybe store it before the ] ) so you'd have the address of where to enter.  Hopefully I'm understanding it right.  Chalk up another one for Forth's unexpected flexibility.


Code:
: SOME_WORD
   do_stuff
   BEGIN
       do_more_stuff
       [ HERE >A ]     \ Save address on auxiliary stack
       yada-yada       <---Optionally enter here
       Condition?
   UNTIL
   etc.             ;
: SOME_OTHER_WORD
      [ A> ] LITERAL ENTER ;

Could also be:
Code:
: SOME_WORD
   do_stuff
   BEGIN
       do_more_stuff
       [ HERE >A ]     \ Save address on auxiliary stack
       yada-yada       <---Optionally enter here
       Condition?
   UNTIL
   etc.             ;
: SOME_OTHER_WORD
      BRANCH [ A> , ] -;

Unless this is desired:
Code:
: SOME_WORD
   do_stuff
   BEGIN
       do_more_stuff
       [ HERE >A ]     \ Save address on auxiliary stack
       yada-yada       <---Optionally enter here
       Condition?
   UNTIL
   etc.             ;
: SOME_OTHER_WORD
      [ A> ] LITERAL ENTER  \ Execute last part of SOME_WORD
      do_yet_more_stuff ;   \ and return to here.

Of course BRANCH can not be used from Forth's command line. ENTER can.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 63 posts ]  Go to page Previous  1, 2, 3, 4, 5

All times are UTC


Who is online

Users browsing this forum: No registered users and 10 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: