My Forth Rethink on Execution Tokens

In which we refactor compiled words again

It’s probably come to your attention that I now have a file called MyForth+Primitives.swift that contains two enormous switch statements. Frankly, I think these need to go away. The easiest way – well, the easiest I’ve thought of – would be make CompiledWord map to Int with a raw value and to create WordList entries for the primitives. That way, I can eliminate all of the switches eventually.

Well, baby steps: first, we’ll create the WordList and dictionary entries based on the existing token property. We do this when we initialise the Forth machine. We use one function: createPrimitive to build both the word lists for the primitives and the initial dictionary.

The code for this is tagged blog-1163-1. Note that, I’m doing this on a branch because it is a big change.

This change, together with some simplifications made possible by it gives us a run time for the fibonacci test as follows:

Time of run: 3.690076811s, words executed: 4778203, mips: 1.2948790078722294
["121393"]

The simplifications are that the compileOnly and immediate flags are stored in the WordList for both defined words and primitive words. I also eliminated branch? which is just a synonym for 0<>branch?.

There is one final simplification which is to get rid of the nasty switch that gets the compile word descriptions. The descriptions of compiled words need to come from the WordList, so I created a new function in MyForth and get rid of the conformance to CustomStringConvertible.

	func descrition(of compiledWord: CompiledWord) -> String
	{
		wordLists[compiledWord.token].name
	}

The above replaces a 150 line switch. I’ve also removed the conformances to CustomStringConvertible for CompiledWord and for WordList. This gives me another slight performance bump:

Time of run: 3.517964204s, words executed: 4778203, mips: 1.3582295677048337
["121393"]

The code is tagged blog-1163-2.

Following the changes detailed above, there are four CompiledWord cases that have associated values:

		case parsedLiteral(Int)
		case undefined(Word)
		case redefined(Word)
		case definition(Cell)

We need to eliminate these, because ultimately, we want CompiledWord to have raw values, which, I hope, will provide us with another performance boost. The .definition case can be done away with by introducing a new primitive called .jsr. This will work very much like .pushNext and then we can pass the cell (which is the word list number to call) as a .parsedLiteral.

One thought on “My Forth Rethink on Execution Tokens

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.