In which I create a dictionary of words and an interpreter
This is series of posts based on a blog by Andreas Zwinkau.
Exercise 2
Create a dictionary of some sort. Initialize it with the words
http://beza1e1.tuxen.de/articles/forth.html+
and2 3 4 + + print
.
This is where things get interesting. Prior to the exercise, Andread says:
Forth maintains a dictionary of words, which maps words to their function. We need to initialize this dictionary with a few builtin words, then we can execute words we read from a stream. … For example, you could have a word + which pops two numbers from the stack and pushs the sum of them. There could be some print word, which pops and outputs. If a word is not found in the dictionary and it consists of digits, it is a number, which is pushed on the stack.
This implies several things. First, I need a dictionary of definitions keyed by words. The words are easy – they are just strings. The definitions are more tricky. They are either a primitive or a definition made up of other words. So, for the moment, I will define the dictionary values with an enumeration consisting of all the primitives as cases and a case for defined words.
typealias WordList = [Word]
enum WordDefinition
{
case plus
case print
case definition(WordList)
}
You’ll note that my case for defined words assumes a definition is a list of words (strings). This is fine for now but is a potential area for performance improvement at a later date. The dictionary will be a Swift Dictionary
but referencing words through it during execution is going to be slower than some sort of compiled form. This is the reason for the typealias
. I will probably want to swap it out for something else in the future.
There will obviously have to be some sort of interpreter. Since the InputParser
is a sequence, this can be a for
loop for now with a switch
inside it to handle the cases.
The print
command requires somewhere to send its output, so we will use a TextOutputStream
for that.
We can have errors e.g. when we come to words we don’t understand. For the moment, we will just throw an exception to handle them. In the future, there will be a way to catch them and have them sent to a TextOutputStream
.
The code for this exercise is at
https://bitbucket.org/jeremy-pereira/myforth/commits/tag/blog-988