Search code examples
forthgforth

Reverse the data stack using loops


I'm trying to reverse the stack using two loops one to send items from the data stack to return stack. And another to get them from return stack to data stack. Unfortunately, it doesn't work & gforth returns the stack underflow error. Below is the code:

: srev ( n n2 n3 n4 n5 -- n5 n4 n3 n2 n)
 6 0 do >r loop 
 6 0 do r> loop ;

1 2 3 4 5 srev


Solution

  • The trouble you've got here is that DO ... LOOP keeps the loop parameters (index and termination value) on the return stack and discards them at the end of the loop. That's why >R and R> must be in balanced pairs during a loop.

    Your code puts a value on the return stack during the loop, which then gets discarded at the end of the loop, leaving a stray loop parameter still there and the whole thing goes haywire.

    You can get the result you want like this ...

    : REVERSE ( i*x i -- i*y ) 0 DO I ROLL LOOP ;
    

    ... though I'm a bit puzzled as to why you'd want to!

    EDIT (after reading comments and ruvim's reply):

    1. Your initial reversing the stack algorithm wouldn't have worked anyway, as a series of R>s reverses the order onto the return stack, and the corresponding >Rs reverses it again back to the parameter stack leaving the order as it was.

    2. Alternative approach, similar to ruvim's but without recursion, is here

        : APPLY ( n*x xt n -- n*x' )
            DUP 1- -ROT                ( n*x n-1 xt n )
            0 DO                       ( n*x n-1 xt )
               2>R                     \ park n-1 xt on return stack 
               2R@ DROP ROLL           \ bring next item to top
               2R@ NIP EXECUTE         \ apply the function to it
               2R>                     \ clear junk off return stack for now
            LOOP                       ( n*x n-1 xt )
            2DROP
        ;
    

    It won't work (because of using ROLL) with anything that affects the stack depth like DROP or DUP, but ' 2* 4 APPLY works just fine!