(* Stack variables. Each stack variable behaves like a stack. You can do

SVARIABLE TEST

and create one. You can treat it like a variable.

5 TEST !

You can push a value onto it.

7 TEST VPUSH

Keep treating it like a variable.

TEST @ .  7 OK

Pop off the value.

TEST VPOP .  7 OK  
TEST @ .   5 OK

My own Forth uses stack variables for BASE >IN the other input buffer variables etc. Easy to save the data. Very convenient.

Stack variables are not efficient. They use twice the memory that dedicated stacks would, and they use threaded lists which are slow relative to real stacks. But none of them overflow until they all do. And they are very convenient, for operations that don't have to be the fastest. *)

\ need a pool of unused items, a linked list

: CELL- [ 1 CELLS ] LITERAL - ;

CREATE SVFREE 0 ,
CREATE SVAVAILABLE 4096 CELLS ALLOT

: LINK-IN ( newlink@ newlink! oldlink -- )
   DUP @ ROT ! ! ; 

: LINK-OUT ( addr -- freelink )
   DUP @ 
   DUP 0= 496 AND THROW \ delete this if it will never underflow
   DUP @ ROT ! ;

: SVMAKE-AVAILABLE ( a-addr #cells -- )
   2DUP CELLS ERASE 
   SWAP CELL+ DUP ROT 2/
   1 ?DO
     DUP 2 CELLS + TUCK !
   LOOP
   SWAP SVFREE LINK-IN ;

SVAVAILABLE 4096 SVMAKE-AVAILABLE

\ Note that you could add a new block of memory to the unused list, any time.
\ You could even allocate a block of memory and use it.

: VCOPY ( a-to a-from -- )
   [ 1 CELLS ] LITERAL DUP D- 2@ ROT 2! ;

\ link address into freelist
: VGONE ( addr -- )
   DUP SVFREE LINK-IN ;

\ get address from freelist
: VGET ( -- addr )
   SVFREE LINK-OUT ;

\ copy stack variable into new link
\ note that svariable address points to data
\ link address points to link
: VNEW ( addr -- )
   CELL+ VGET        \ a1 link
   2DUP SWAP VCOPY  \ link a1 
   SWAP ! ;

: VOLD ( addr -- )
   CELL+ DUP LINK-OUT TUCK
   VCOPY VGONE ;

: VPUSH ( x addr -- )
   DUP VNEW ! ;

: VPOP ( addr -- x )
   DUP @ SWAP VOLD ;

: VDEPTH ( addr -- u )
   CELL+ 1 BEGIN
     OVER @ WHILE
       1+ SWAP @ SWAP
   REPEAT NIP ;

: SVARIABLE
   CREATE 0 , 0 , ;

\ It would be possible to add a third field to make a linked list of all the stack variables. \ That would make it easier to keep track of them all, in case you wanted to do that.