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
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):
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.