Last weekend I eliminated the last Swift from the interpreting loop. There are now two pre-predefined words: an outer loop that reads a line of text and calls the the interpreter from the last post and the inner loop that interprets words from a line. The code for each looks something like this:
: .readLoop 2 branch .interpreter refill -4 0<>branch? ;
: .interpreter
6 branch
.interpretOrCompile 2 0=branch? execute
.wordForInterpreter 1 + dup 1 - c@
dup
-17 0<>branch?
drop drop
;
In both cases, it helps to understand that the loop condition is at the end of the code, instead of the natural location at the beginning and the first instruction, therefore, branches unconditionally to the loop condition calculation i.e.
while calculate loop condition
do stuff
becomes
branch calculate
loopBody:
do stuff
calculate:
calculate loop condition
branch if true loopBody
This may seem a bit odd, but it saves a branch execution on every iteration of the loop over putting the loop condition at the front.
.readLoop
is word 0 and .interpreter
is word 1.
The Swift code is now
wordNumber = 0
wordIndex = 0
try resume()
We just point the Forth machine at the read loop and tell it to go.
That ends the creation of a Forth interpreter in Forth, so the branch is now merged back into master and we can get on with defining the remaining core words.