wo: Stacks

At some point the question of stacks in wo needs to come up. How many, how do they work, how do we manipulate them. As mentioned in the first post in the matter, I’ve been operating under the premise of a stack that does not shrink (unless cleared). It takes the theoretically-infinite stack of RPL, and combines it with the repeating bottom of RPN. Thus (pseudocode, obvs):

> 1 2 PRINT_STACK
1
2

> 3 PRINT_STACK
1
2
3

> DROP PRINT_STACK
1
1
2

This could be really useful, or really unwieldy. Time will tell. Instructions 4 and 5 (tentatively REGISTER and DOUBLE, respectively) will be discussed in a future entry, but instruction 6 is our first stack manipulation instruction: CLEARPST. Resets the stack to a single value, whatever the top of the stack happens to be. So, with our stack from before:

> CLEAR_STACK PRINT_STACK
2

I changed it to ‘STACK’ for my pseudocode, so why am I calling it ‘PST’ in the instruction set? I’m planning on more than one stack, and as of yet we are only dealing with the Primary STack. There is also almost certainly going to be a $tring STack, and possibly a Secondary STack. Unlike ‘PST’, ‘$ST’ will shrink, and will be capable of emptiness. Strings will not be its only function, but a simplified means of manipulating strings is heavy on my mind. I envision FOLD and UNFOLD instructions that blow a string from ‘PST’ up into a stack of ASCII values on ‘$ST’ and vice versa, with PICKs and other bog-standard stack manipulation tools aiding in string manipulation. It won’t be efficient, particularly with lower instructions, but it will be doable.

One important instruction is going to be WRITEINS. WRITEINS will allow the programmer to overwrite any instruction. Any and all nonexistent instructions are, by default, treated as NOPs, and are also fair game. Thus, one can essentially write functions, either by destroying unneeded instructions, or opening up new ones. WRITEINS will need a scratchpad; it will consume an entire stack. ‘$ST’ could be used for this, but I’m also throwing around the idea of ‘SST’. This secondary stack would behave like ‘$ST’, in that it would be capable of emptiness, would start empty, and would shrink with drops. It would be a temporary stack, the aforementioned scratchpad. Switching from ‘PST’ to ‘SST’ could theoretically pass values, math, input, and manipulation could then be done on ‘SST’, but switching back to ‘PST’ would empty ‘SST’, pushing the top of the stack to ‘PST’.

This would allow for things like string manipulation between ‘SST’ and ‘$ST’ without cluttering up ‘PST’, for entering instructions using WRITEINS, and for inputting DOUBLEs without growing ‘PST’. It’s a lot more to implement, and it wastes instructions. Much of it can be done with ‘$ST’, so these instructions will come later (if at all). But it’s a lingering thought.

Stack manipulation is the name of the game at this point in the instruction set: DROPPST to drop a value from ‘PST’, YANKPST to pop a value off of the stack and duplicate the value at the respective stack index (0 YANKPST would be akin to DUP), PICK$ST would do the same for picking from ‘$ST’ onto ‘PST’ (and if fed MNum as an index, would fold the whole stack into a string on ‘PST’), and PUT$ST would be the opposite, popping a value off of ‘PST’ onto ‘$ST’ and unfolding it if it’s a string. This brings us into wo5, and I need to ponder the relative importance of DROP vs. PICK manipulations. But for the time being…

Current Instruction Set:

0, 0, PRNTPST:
Print the contents of the primary stack (PST)
1, 1, GOTO:
Pop top of stack, go to corresponding word
MNum: Go to word indicated by storage register R2 (more on this later)
Nonexistent word exits
2, 10, ADD:
Pop two values off of the stack, push their sum
3, 11, SKIPZERO:
Pop one value off of the stack, if == 0, skip all words through next instruction
4, 100, REGISTER:
Pop two values off of the stack, set register indexed by first to value of second
MNum: Push value of register indexed by first
5, 101, DOUBLE:
Pop two values off of the stack, push value created by treating the popped values as a double number
6, 110, CLEARPST:
Empty PST, pushing the top of stack as its only value
7, 111, YANKPST:
Pop a value off of the stack, push the value of the stack entry indexed by the popped value
MNum: Could potentially cause a DROP
Negative values indexed from bottom of stack
8, 1000, PICK$ST:
Pop 1 value off of PST, pop the value off of $ST with the index of the value popped from PST
MNum: Fold entire SST into string on PST
Negative numbers index from bottom
9, 1001, PUT$ST:
Pop one value off of PST, push onto $ST
If value is a string, unfold entire string onto $ST