The next thing I've been tackling has been the verb/grammar code. The goal here is to represent the logic/data structures from this section of the #PunyInform library: https://github.com/johanberntsson/PunyInform/blob/master/lib/grammar.h#L7-L225
It looks like a combinatorial explosion of possible prepositions in a large space of possible sequences, along with placeholders for object search conditionals. It feels like the kind of thing that needs a lot of core just to map it all out. Sure, I have my input words compressed to single 12-bit integers, but there's a lot of repetition in the source there and it seems like a mess to represent.
I made a list of all the tokens in this thing, and came up with 32 values (including a null). Well, that's neat! I could decide that if the most significant bit of a tanner is `0`, it's a lookup into a table of 12-bit values. I have some space left in my compression scheme for ideas like "object in scope" or "object in inventory" (which can gobble multiple words), so I can handle common cases like `INVENTORY`, or `GET LAMP`, or `TURN ON LAMP`. I map the `TURN` verb into a pair of indices for `ON` and *noun*, pointing out to our equivalent of the Puny `SwitchOn` function in the #PDP8 game code.
Okay, but what about all that `'in'/'into'/'inside'/'on'/'onto'` stuff? Well, If the tanner's most significant bit is `1`, then I treat it as a sort of pointer into the second half of my grammar index. So that might look like this:
37. `IN`, `INTO`
38. `INSIDE`, *37*
39. `ON`, `ONTO`
40. *38*, *39*
So I might have `GET` mapping a grammar word of [*40*,*noun*] to the `ENTER` procedure, so that `GET INSIDE BICYCLE` and `GET ONTO BICYCLE` will both call the same code. The grammars use 3 words per mapping, and make use of a table of 64 words. This feels more comfortable for the type of system I'm writing here.
Yes, this is just #LISP cons cells, and I love that.
Now I just need to write all this...