The goal of the
is to produce an implementation
of PyFL that is much faster than the current lazy interpreter,
which repeatedly decodes the expression tree.
The current interpreter produces Basic PyFL, with all the advanced
while loops) implemented by translation.
Our strategy is to translate Basic PyFL
into the machine language for a FORTH-like stack-based
The MABWA machine has a conventional FORTH like design, with a reverse polish instruction language. To add 2 and 3 you push 2 then 3 on the implicit value stack, then execute the add instruction that pops the top two elements of the stack, adds them, then pushes the result on the stack.
delimit code blocks, sequences of instructions
that will be manipulated but not immediately executed.
The MABWA machine pushes these two blocks onto the stack
when it encounters them. They become the top two elements of
The next stage is to assemble the MABWA code into machine language.
The result is still text, but at a lower level and more concise.
For example, addition is denoted by
load becomes three instructions.
" causes the
name of the variable (a string) to be pushed on the stack
without being examined
(as an instruction). Then the instruction
looks up the definition of the variable - a code block
(not shown) which is then executed.
The definition is found in the current environment, which is stored in a register.
An environment is an array of frames, and each frame is a dictionary of code blocks indexed by variable names. The definitions in a frame are mutually recursive and the next frame in the environment array is the textually enclosing one.
$ operator locates the frame with the
needed definition and executes
the definition in the possibly different environment
beginning with the frame in which the definition was found.
The current environment is pushed on a stack during
More precisely, suppose that the current environment
e is the array
[f1, f2, f3, ...] of frames and that we
are looking for the definition of
We consult f1 and f2 without success
but find that f3 has a defining
code block b associated with
v we push e on a separate
environment stack and put the reduced environment
[f3, f4, f5, ...]
in the environment register. Then, we execute b.
When b is finished we pop e off the
environment stack and put it back in the register.
Environments come into play during evaluation of function calls. There are two environments, the environment in which the function was called and that in which it was defined. The body of the function is evaluated in the defining environment but the actuals are evaluated in the calling environment.
We plan to write a test interpreter in Python to check out the logic. But for speed, the ultimate goal, we'll use Apple's Swift.