Has anyone else implemented an extra stack ( or more) in Forth? How did it affect your programming?
I've implemented an extra stack in Fleet Forth that I mostly use for a spare data stack. I've defined the following parallels for the return stack words:
Code: Select all
>R >A
R> A>
R@ A@
DUP>R DUP>A
2>R 2>A
2R> 2A>
Since this extra stack, which I call the auxiliary stack, is rignt up against the return stack and right up against the area the C64 uses to keep track of which files are open, the words to move data to and from the auxiliary stack ( or aux stack ) test for overflow/underflow.
I usually use the aux stack to hold control flow data so I can do more with CODE words while keeping the source sane and avoiding hand calculated offsets. The aux stack words CS>A and A>CS move the control flow data on the control flow stack ( data stack ) to or from the aux stack. I also use the aux stack to hold temporary addresses to be resolved later, when I want one CODE word to branch or jump into another CODE word at a certain location.
I have also used these words in place of their return stack counterparts when defining a new word ( for my decompiler ) to test it. Once it was working, I changed the aux stack words to the faster return stack words.
It's even been helpful in hand tracing the execution of a system word I was modifying ( to make it easier to support more drive types ).
On another thread, SamCoVT mentioned:
Aux stack to the rescue!
First, some temporary redefinitions to make things a little safer, just in case:
Code: Select all
: >R >A ;
REDEFINE: >R
OK
: 2>R 2>A ;
REDEFINE: 2>R
OK
: DUP>R DUP>A ;
REDEFINE: DUP>R
OK
: R> A> ;
REDEFINE: R>
OK
: 2R> 2A> ;
REDEFINE: 2R>
OK
: R@ A@ ;
REDEFINE: R@
OK
Here is modified source for one of Fleet Forth's system words:
Code: Select all
// (DR/W)
HEX
NH 2 CONSTANT DSI
: (DR/W) ( ADR BLK# R/WF CNT -- )
1- SPLIT 2>R T&S (IS) DSI
R> 0
?DO
>R 2OVER 2OVER R@ 100 SR/W
2>R
100 UNDER+ DSI + 2 PICK /MOD
2R>
ROT UNDER+ R>
LOOP
R> 1+ SR/W DROP ;
' (DR/W) IS DR/W
And here is the log of tracing it by hand:
Code: Select all
HEX OK
2 DRIVE OK
PAD 315 1 B/BUF OK
.S 5934 315 1 400 OK
.AS EMPTY OK
1- SPLIT OK
.S 5934 315 1 FF 3 OK
2>A OK
.S 5934 315 1 OK
T&S81 OK
.S 28 5934 24 50 0 1 1 OK
0 VALUE DSI OK
TO DSI OK
.S 28 5934 24 50 0 1 OK
A> 0 OK
.S 28 5934 24 50 0 1 3
0 OK
. . 0 3 OK
>A 2OVER 2OVER A@ 100 OK
: .SRW CR . . . . . . ; OK
.S 28 5934 24 50 0 5934 24
50 0 1 100 OK
.A OK
.S 28 5934 24 50 0 5934 24
50 0 1 100 A 0 OK
D. A OK
.AS FF 1 OK
.S 28 5934 24 50 0 5934 24
50 0 1 100 OK
.SRW
100 1 0 50 24 5934 OK
2>A 100 UNDER+ DSI + 2 PICK /MOD OK
.S 28 5A34 25 0 OK
2A> ROT UNDER+ A> OK
.S 28 5A34 25 50 0 1 OK
>A 2OVER 2OVER A@ 100 .SRW
100 1 0 50 25 5A34 OK
2>A 100 UNDER+ DSI + 2 PICK /MOD OK
2A> ROT UNDER+ R> OK
.S 28 5B34 26 50 0 1 OK
.AS FF OK
>A 2OVER 2OVER A@ 100 .SRW
100 1 0 50 26 5B34 OK
2>A 100 UNDER+ DSI + 2 PICK /MOD OK
2A> ROT UNDER+ A> OK
.S 28 5C34 27 50 0 1 OK
R> OK
.S 28 5C34 27 50 0 1 FF OK
1+ OK
.SRW DROP
100 1 0 50 27 5C34 OK
.S EMPTY OK
CONSOLE
There is one place in the log where I inadvertently typed .A instead of .AS , placing a double on the data stack rather than displaying the contents of the aux stack. I promptly removed it and continued tracing by hand.
Had I accidentally typed >R rather than >A ( because that is what the source has ) it would have been fine thanks to the temporary redefinitions. Accidentally typing ?DO or LOOP would not have caused a problem other than clearing all stacks when it aborted with the message "FOR COMPILING".