welcome back again. The part of the articles rounds up the discussion on the
Interpreter and disusses some code uploaded in the attachment.
The Interpreter again
The Interpreter class delegates the hard work to the Memo class; it has a Memo
object as one of its members to delegate to:
Expand|Select|Wrap|Line Numbers
- protected Memo memo= new Memo();
- public Memo memo() { return memo; }
1) the Stack object on which all calculations take place;
2) the Scope object that takes care of all local variables;
3) the Memo object that memoizes previous user function calls.
The Interpreter itself doesn't do much, i.e. it just invokes the execute method
on all the Instructions in the Code list. The Instruction thing is an interface
which all real Instructions have to implement.
As you can conclude from the simplicity of the Interpreter: most, if not all, of
the 'intelligence' is implemented in the Instruction implementations. The Interpreter
only supplies the mechanics to run a compiled program.
The Instructions are very much unlike 'real' machine code instructions. Our
Instruction classes implement a much higher level functionality. The next part(s)
of this article show the most important instructions and the mechanism they
implement and how more instructions can be added to the set. Mostly Instructions
implement a function, a list function or a quoted object.
Concluding Remarks
This article part contains an attachment: a zip file with all the source code
so far in it. This code is supplied "as is" and I take no responsibility whatsoever for it. It is quite harmless though: there's a Main class in the compiler
package that you can use to play with the entire thing a bit.
This is what it says when you invoke it in an incorrect way:
Expand|Select|Wrap|Line Numbers
- usage: java compiler.Main <infile> [-i ] [-o <outfile>] [-d] [-m] [-r | -t]
- <infile> a file that contains the source
- -i consider <infile> compiled code
- -o <outfile> save compiled code to <outfile>
- -d dump compiled to to System.out
- -m turn on memoization (default is off)
- -r run the compiled code
- -t trace the compiled code
- the content of the stack is displayed at the end
Scrutinize through the code and try to understand it all. An explanation can
be found in the Compiler articles but feel free to comment and/or ask questions.
The Main driver always reads from the <infile>. When you don't supply the -i
flag the driver assumes that it has to compile source code, stored in that file.
If you do supply the -i flag the driver assumes that the file contains compiled
code. If you supply the -o <outfile> arguments the driver will save the compiled
code to that file. When you supply the -r or the -t flag the driver will start
the Interpreter for you and runs the code. When execution has finished the stack
will be printed. When the code is run with the -t flag specified, every instruction
will be printed along with the current stack values just before it is executed.
The -m flag turns memoization on and the -d flag dumps the compiled code to the
System.out stream in a human readable form before execution starts (if the -r or
-t flag are passed on the command line) or just before the driver terminates.
Play with it a bit, e.g. for starters store the following content in a file and
try to compile and run it:
Expand|Select|Wrap|Line Numbers
- 1+2;
- 3+4;
- 5:6:+7+8;
kind regards,
Jos