Forth stack operators: Difference between revisions
No edit summary |
(+cats) |
||
(One intermediate revision by the same user not shown) | |||
Line 34: | Line 34: | ||
pick ( a0 .. an n -- a0 .. an a0 ) |
pick ( a0 .. an n -- a0 .. an a0 ) |
||
roll ( a0 .. an n -- a1 .. an a0 ) |
roll ( a0 .. an n -- a1 .. an a0 ) |
||
// examples: reimplement primitives |
|||
: dup 0 pick ; |
|||
: over 1 pick ; |
|||
: swap 1 roll ; |
|||
: rot 2 roll ; |
|||
There are also stack debugging aids in [[Open Firmware]]. '''.s''' will print the current contents of the stack, and '''showstack''' changes the prompt to show the top items of the stack between each command. |
There are also stack debugging aids in [[Open Firmware]]. '''.s''' will print the current contents of the stack, and '''showstack''' changes the prompt to show the top items of the stack between each command. |
||
Line 41: | Line 46: | ||
.s ( [s] -- [s] ) |
.s ( [s] -- [s] ) |
||
showstack |
showstack |
||
[[Category:Forth]] |
|||
[[Category:HowTo]] |
Latest revision as of 16:41, 29 August 2007
Forth has a set of primitive words which are used to reorder data on the stacks. They are similar to the register move assembly instructions found in microprocessor instruction sets. A goal of a good Forth programmer is to minimize the use of these words, since they are only moving data around instead of doing useful work. Reference implementations for the less basic operators are also given.
dup ( a -- a a ) ?dup ( a -- a a | 0 ) dup if dup then ; drop ( a -- ) swap ( a b -- b a ) over ( a b -- a b a ) rot ( a b c -- b c a ) -rot ( a b c -- c a b ) rot rot ; nip ( a b -- b ) swap drop ; tuck ( a b -- b a b ) swap over ;
There are a few operators which move data between the data stack and the return stack. This can be useful for stashing data away temporarily in order to work on data deeper on the stack, or to make a single unnamed local variable. Use of these words must be balanced within a definition, since the return stack is also used for return addresses. Also, stashing data on the return stack cannot cross into a DO-LOOP construct, since the loop index is stored on the return stack.
>r ( a -- R: a ) r> ( R: a -- a ) r@ ( R: a -- a R: a )
Most of these operators also have a double-cell form with a "2" prefix, where the same operation is performed on pairs of cells. This is useful for operating on double-cell data, such as strings and double precision numbers. 2dup is often used for doing binary tests, for example ( a b ) 2dup > if swap then .
2dup ( a b -- a b a b ) over over ; 2drop ( a b -- ) drop drop ; 2swap 2over 2nip 2tuck 2rot 2>r 2r> 2r@
Pick and Roll are the generic operators which treat the data stack as an array. If you find you need to use them, you are probably doing it wrong. Look for ways to refactor your code to be simpler instead.
pick ( a0 .. an n -- a0 .. an a0 ) roll ( a0 .. an n -- a1 .. an a0 ) // examples: reimplement primitives : dup 0 pick ; : over 1 pick ; : swap 1 roll ; : rot 2 roll ;
There are also stack debugging aids in Open Firmware. .s will print the current contents of the stack, and showstack changes the prompt to show the top items of the stack between each command.
clear ( [s] -- ) depth ( a1 .. an -- a1 .. an n ) .s ( [s] -- [s] ) showstack