brhfl.com

wo: Numbers

A draft of this post began:

A few thoughts on numbers in wo. Numbered input is pushed to the stack via LSB==1. LSB==0 signifies an instruction, so in either case, effective word size is 1 bit less than total word size. The stack itself won’t care what sort of numbers it’s holding, input is the tricky part. wo3 would allow you to enter the integers 0-3, or 2-1 depending on unsigned vs. signed input. wo4 0-7 or 4-3. These aren’t big numbers to work with, so getting instructions in early to allow for more complicated input would be welcome. The easiest solution here is simply getting the WORDSIZE instruction out of the way as early as possible, ideally in two bits. With signed input, this would only get a user up to a 4-bit word size with 6 bits of input. Unsigned, a user could get up to 6-bit word size in the same 6-bit input, which raises the question of whether allowing a single word input of 1 is more important than more immediate access to slightly higher integers. Signed input would reduce the need for a sign-changing instruction at the low end of the set, and there are little hacks that could be put in place – for example, if 1s’ complement was used instead of 2s’, 0 could act as a stand-in for the next highest byte size or the like. Thus 6 bits of input could immediately kick word size up to a full byte.

As outlined in this post killing off WORDSIZE, I have changed my thoughts on that matter. I do think input will (by default) be 1s’ complement, with 0 receiving special treatment, what I am internally referring to as the Magic Number or MNum. MNum would allow some instructions to serve multiple purposes, which could theoretically put us on the path to larger integers at lower word sizes. Additionally, MNum can act as a stand-in for a predetermined value for other instructions, again opening up some integer growth options.

One way to increase the number of integers available for input would be with a DOUBLE instruction, inspired a bit by Forth. In Forth, double-length numbers are simply handled as two single-length numbers back-to-back on the stack1. Special operators deal with pairs of stack entries at a time for the sake of double-length arithmetic and stack manipulation. In wo, the size of stack values is of little concern compared to our ability to input. So my proposal is a DOUBLE instruction that pops two values off the stack as if they were a Forth-style double-pair, and pushes the combined result. Thus (unsigned, wo32) 111 111 DOUBLE would result in 15.

Finally, we’ve been dealing in integers here, and as far as I am concerned input will be restricted to integers. Yet the stack itself won’t be, so simple divide by 10/100/&c. operations will allow for (admittedly inefficient) fractional input. Further down the line, particular instructions could be introduced to divide by ten, divide by 100, and so on, but early on in the instruction set simple division should be enough – if one can enter a ten. This would mean briefly increasing word size or using doubles. Alternatively, we could use the same 0 hack as above, but use it to represent the lowest multiple of ten unachievable at the current word size. We could, in fact, always turn 0 into a ‘magic number’ that certain instructions would treat in a special way. It would simply be interpreted as zero if an instruction didn’t have a special rule for it. In fact, depending on the utility of the ‘magic number,’ it could even be the initial value of the stack.


  1. Here’s the relevant chapter of Leo Brodie’s Thinking FORTH, freely available and hosted by FORTH, Inc. The book is a useful read even for programmers with no interest in Forth, and the linked chapter offers a good explanation on signed number representation and binary math as well as double-length numbers. ↩︎
  2. Purely hypothetical; I think instructions 2 and 3 are set in place now (that’s coming next), and DOUBLE is shaping up to be in the 4-7 block at least. Creating double-length numbers from 1s would be tedious at best, and I think wo3 will be suited for far simpler tasks. With the current instruction set, a truth machine takes exactly one byte, though (it’s c). ↩︎