I’ve been thinking about the proper way to get Forth onto the Mill architecture. Like you said, the operations/words are the easy part, once the double stack system is set up.
My idea was to steal from the cheap
call in the Mill to serve the function of the return stack (though we lose the ability to abuse the return stack for other needs). The data stack makes me think of the belt. colorForth uses an 8 item circular buffer, but is for a different use case. Does the compiler keep track of the virtual stack like this:
virtual stack: 3 4
belt: 3 4
forth word: +
virtual stack: 7
belt: 7 3 4
The belt seems to be much more along the lines of a purely functional language where GC is cheap; whenever something falls off the belt. Here I am torn between:
1) Move towards having a Forth where the stack effects are known and verified at compile time. This allows the compiler to keep track of the “virtual” stack. Compiler manages and saves items to a software defined stack otherwise.
1b) use the scratchpad for the remainder of the stack.
2) keep is a “small” Forth: only use the belt, words CANNOT use more than the belt or temp usage of the scratchpad. Restricted, but simple.
3) go very simple; words use the belt+scratchpad, but words themselves are responsible for putting everything onto a software defined stack. This is simpler, but slower as everything has to go through indirection.
4) Deviate from Forth stack-based concept and use a belt-based concept.
I would enjoy trying these and building upon them. And any suggestions would be appreciated.