I've started exploring Forth using Gforth on a Kali Linux computer. Thinking about stacks I always imagine the picture of the HP calculator stacks like so:
T <- bottom of the stack
Z
Y
X <- top of the stack
So I have written two words, the first one prints out the inverted stack, the second prints the floating point stack in inverted form. My assumption was that both routines should be 100% identical with the exception of stack-specific words, e.g. pick
and fpick
, .
and f.
. But it turned out that I had to modify the fprstinv word in one line. Here they go, prstinv
and after that fprstinv
:
: prstinv ( print inverted stack, works correctly )
depth 0 >
if
cr
depth 1 + 1
do
depth i - pick .
i 1 =
if
." <- Bottom" cr
else
i depth 1 - <
if
cr
then
then
loop
." <- T O P"
then
;
: fprstinv ( print inverted f-stack, works incorrectly )
fdepth 0 >
if
cr
fdepth 1 + 1
do
fdepth i - fpick f.
i 1 =
if
." <- Bottom" cr
else
i fdepth 1 - < \ creates the error in the formatting
if
cr
then
then
loop
." <- T O P"
then
;
fprstinv messes up the formatting:
3. <- Bottom
2. 1. <- T O P ok
For the correct formatting see below...
If you run prstinv with three numbers on the stack and then prstinv, you'll see the correct output. The following version of fprstinv works correctly when altered to look as follows:
: fprstinv ( print inverted f-stack, works correctly but differs from prstinv in one line )
fdepth 0 >
if
cr
fdepth 1 + 1
do
fdepth i - fpick f.
i 1 =
if
." <- Bottom" cr
else
i fdepth < \ does not create an error
if
cr
then
then
loop
." <- T O P"
then
;
The correct outputs as intended by me are:
.s <3> 3 2 1 ok
f.s <3> 3.000000000000E0 2.000000000000E0 1.000000000000E0 ok
prstinv
3 <- Bottom
2
1 <- T O P ok
fprstinv
3. <- Bottom
2.
1. <- T O P ok
I don't understand the different behavior: Both stacks should be the same in terms of structure and analog properties like depth and fdepth. So, both words should be the same in terms of structure, looping parameters and if-conditionals.
I appreciate even small hints as well as assumptions which could help to find further information!
Thanks a lot!
The reason of divergent behavior in your code is as follows.
In the case of the data stack:
i
places a number on the data stack, and this number is counted in the result ofdepth
. And1 -
eliminates this contribution ofi
.In the case of the floating-point stack:
i
places a number on the data stack, and this number is not counted in the result offdepth
(since it counts the items on the floating-point stack only).To make behavior in the second case as in the first case you have to remove
1 -
, as:Or you can change both variant as follows:
(I.e., place the depth on the stack before placing other arguments)
One more advice: use early
exit
to decrease the number of nesting levels.Instead of:
do:
Rationale: Why I Don't Use Else When Programming (YouTube)