Shi
|
Forth has the notation of three different stacks:
Shi only uses two physical stacks, the data- and the return-stack. This is possible because all control-flow words (e.g. if, else, then, begin, until, while, ...) are so called "compile only" words which means that they can only be used when creating a new definition. The way the standard phrases this is that interpretation semantics are undefined.
So this works
whereas this doesn't.
The principal difference is that during compilation mode inside the colon-definition the user can't alter the data-stack which makes it perfectly safe to store branching information on it.
Data-stack
The data-stack in Shi is explicit. Two physical registers are reserved for it. There is tos which is short for top-of-stack and dsp which is the data-stack-pointer. Upon pushing to or popping from the stack values are stored or loaded at the address in dsp.
The stack size itself can be adjusted with the macro SHI_STACK_SIZE.
Control-flow-stack
Usually control-flow words have a 1:1 relation between the word that creates a branch and the word that has to resolve it. forth-standard.org offers a very nice visual representation of control-flow words here. The problem is that there are two exceptions from this 1:1 relation which are endof and leave. Those words can nest an arbitrary number of times and even mix with other control-flow words. To avoid any clashes endof and leave push their control-flow values by using the control-stack-pointer. csp touches the same physical memory as dsp but pushes from stack begin towards the end. Since csp is less commonly used it's only stored as variable.
Return-stack
The return-stack is implicit and shared with the main application. This means that the return-stack is basically whatever the stack-pointer of the ARMv7-M architecture points to. Use of return-stack is generally discouraged as incautious use can not only crash Shi but the entire system.