In which I simplify the execution cycle
Every word now has an execution token and most words are interpreted using the function execute(token:,wordStream:,index:, output:)
. There are still a couple of words that have to be executed outside of this due to their CompiledWord
having an associated value. Thus we have this ugly bit of code:
switch wordDefinition
{
case .parsedLiteral(let number):
flushDataStackTop()
stackTop = number
case CompiledWord.undefined(let word), CompiledWord.redefined(let word):
throw Error.unrecognisedWord(word.string)
default:
try execute(token: wordDefinition.token,
wordStream: wordStream,
index: &index, output: &output)
}
wordsExecuted += 1
Parsed literals can be changed to be a sequence of two CompiledWord
s e.g. push 3
where the semantics of push
are “put the next compiled word on the stack”. Undefined and redefined words shouldn’t even get here. They are used when the interpreter is looking for a word to go with a definition or quote. We should deal with them at a higher level.
Having made the changes, the code is now cleaner at the expense of being significantly slower.
Time of run: 4.510405708s, words executed: 4778195, mips: 1.0593714422463212
["121393"]
The code for the above is tagged blog-1151-1.