In which I evaluate some strings
evaluate word is next on the list of core tests. This allows a Forth program to evaluate a string as if it were another Forth program. The simplest way to implement this would seem to be to implement a stack of sequences of input characters.
evaluate then simply pushes a string (well, actually a character iterator) onto the stack.
The Forth program therefore needs to be able to manipulate the input parser, so I have changed it from being a local variable in the
interpret(input:output:) to being a property of the Forth machine. I have also added functions to push and pop character iterators.
Having implemented the above, the unit tests seemed to pass. The results are in tag blog-1318. However, all is not as it seems, as exemplified by the following unit test.
predefine(""" : jp2 s" 1 1+" evaluate 99 ; """)
t("jp2" , expected: "2 99", debug: true)
The test fails because 99 gets onto the stack before 2. This is because my code inserts the evaluate string into the input character stream but does not immediately evaluate it. Instead, it unwinds the stack and executes the remaining code in
evaluate needs to exit out of the resume loop to pick up the next word before executing the rest of the definition that it is in.
It’s actually quite easy to make this happen: you just set the word number to zero, and the loop exits, because it thinks it’s got back to the interpreter level. However, setting the word number to zero overwrites the position in the currently executing word of the word after the
evaluate. So we have to push it onto the return stack before setting the word number to zero…
..several weeks later…
Things did not go as planned. I’ve tried to get
evaluate working but the basic execution loop was so encrusted with different modalities and states and other horribleness, that I’ve decided to drop implementation of
evaluate for now and do some serious refactoring.