forthgforth

gforth : using the return stack


I am in the process of learning GForth.

Now trying to understand and get some practice using the return stack.

Can somebody with more experience tell me what I am missing ?

Here is the issue.

If use these definitions, it all works as I expect :

: syr dup 2 mod 0 = if 2 / else 3 * 1 + endif ;

: collatz begin dup 1 <> while dup . syr repeat . ;

These area a few tests:

1 collatz 1  ok
2 collatz 2 1  ok
3 collatz 3 10 5 16 8 4 2 1  ok
4 collatz 4 2 1  ok

Now comes the question. Changing the previous code I want to make use of the return stack. Using these definitions:

: syr dup 2 mod 0 = if 2 / else 3 * 1 + endif >r ;

: collatz { ini } ini begin dup 1 <> while dup . syr r> repeat . ;

I also expect things to work, but it doesn't.

This is a sample test:

2 collatz 2
:424: Invalid memory address
2 >>>collatz<<<
Backtrace:
$7FC88491B470 ;s
$7FC88491B500 syr

Solution

  • The returns stack in Forth can be only used to temporary store data within a definition. It cannot be used to pass data across definition boundaries.

    See the section 3.2.3.3 Return stack of Forth-2012 (the standard):

    • All values placed on the return stack within a definition shall be removed before the definition is terminated or before EXIT is executed.

    Your second definition for syr violates this restriction in the fragment >r ;.

    If you need an additional stack, you can just implement it or load an existing implementation, and use it at your own discretion (for example, see a library zstack.f).

    And, please, include stack diagrams in your definitions, especially when you share your code.