"The" stack and the return stack
Standard Forth has two built-in stacks, the data stack, and the return stack. The data stack is so important that it is simply called "the" stack, unless you have to distinguish it from some other stack. I will assume that you are familiar with it, and will not discuss it further.
When a word is invoked, the inner interpreter puts the next address on the return stack. When the word is completed the top item on the return stack is popped into a register called ip (instruction pointer), and execution continues from there. Most Forths that run on Intel machines use the BP register for ip.
Since the return stack is actually used only on invocation and completion, , it is available as a kind of catch-all in between. One common use for the return stack is to store do ... loop parameters. Anything added to the return stack during the execution of a word must be removed before the word ends, and the same is true for a loop.
Words that affect the return stack
A stack is not an array
In some Forths, for example, F83, the data stack and return stacks are located entirely in RAM and can be handled as arrays. In others, this is not so; for instance, many Forths gain speed by keeping the top element of the stack in a register.
For this reason, an ANSI standard program cannot make any assumptions about where the stacks are located or how they are implemented. pick ( .... n -- .... x) is available to copy the nth stack item onto the top of the stack.
Software stacks are sometimes called "pseudostacks." Actually, they are genuine stacks, and I prefer the term "software stack" or "LIFO", which stands for "last in first out." That name is taken from the language of finance, where it is used to describe a method of accounting for inventory.
I have implemented LIFO's as a kind of specialized array with a pointer. Pushing a quantity onto a software stack removes it from the parameter stack, stores it in the array, and bumps the pointer; popping does the reverse. A program can have any number of LIFO's. If only one is needed the code can be simplified. In my implementation, there is protection against underflow but not against overflow.
Code meets requrements for an ANS Forth standard program.
Updated: June 18, 1996
\ Software stacks (see text for documentation) : lifo ( n -- ) ( -- adr) create here cell+ , cells allot does> ; : push ( n lifo -- ) swap over @ ! cell swap +! ; : pop ( lifo -- x ) cell negate over +! dup @ swap over >= abort" [pseudostack underflow] " @ ; : pclear ( lifo -- ) dup cell+ swap ! ; : pbounds ( lifo -- addr1 addr2 ) dup @ swap cell+ ;