| CIT 594 Bugs
Interpeter, part 1 Spring 2008, David Matuszek |
Given a program in the Bugs language, you now can create an AST (Abstract Syntax Tree) for it. The next step is to interpret the AST, so that your Bugs program "does something."
In this assignment you will write the first half of the interpreter. (The next assignment will be to complete the interpreter.) We will leave three things for later: Implementing function calls, displaying the bugs' actions on the screen, and coordinating the actions of multiple bugs.
Now might be a very good time to review The Bugs Language.
Name your Bug interpreter class Bug.
Two fundamental methods are needed:
public double
evaluate(Tree<Token> tree), for parts of the
tree (mostly, expressions) that need to return a value, andpublic void interpret(Tree<Token>
tree), for parts of the tree (such as statements) that do
not return a value.interpret with the
root node of a Bug (the AST representing a <bug
definition>. To interpret this node, you interpret
each of its five children, as follows:name of the Bug in an
instance variable.var
declarations.loop node will walk its children
repeatedly). Some nodes, such as an assignment node, may cause certain
children to be evaluated, rather than interpreted,
and it will be obvious when to do this.Note: Although the interpretation proceeds top down, starting at theFor keeping track of variables and their values, write the following two methods:Bugroot, you will need to write the methods by starting at the bottom and working your way up (just as you did in theRecognizerandParser), so that you can test as you go. Of course, full JUnit testing is required.
void store(String variable, double value)
is used to perform the assignment variable=value.double fetch(String variable) is
used to retrieve the current value of variable.
(If there is no such variable, throw some kind of RuntimeException.)HashMap<String, Double>
to keep track of the values of variables. However, there are three
variables that need to be treated specially: x,
y, and angle. These
do not go into the HashMap, but are instance variables
of the Bug class, for reasons that should become clear when we
implement functions. Make sure that store and
fetch handle these three variables correctly.
These are more-or-less in the order given in the Bugs Grammar, not in the order you need to write them. Remember, bottom up!
Interpreter class, not in a Bug
class.programBug
object. The constructor should take as arguments the Bug's name, the
Bug's AST, and a reference to the Interpreter
that created the Bug. Save each Bug in a HashMap<String,
Bug> , using the Bug's name as key. AllbugsHashMap<String,
Double> to store the var
declarations (with initial values of 0.0). HashMap<String,
Tree<Token>> to store the function
definitions.functionBug
class should have an
instance variable
HashMap<String, Tree<Token>> functionsfunction
node as the
value. (Actually interpreting the function will be done by a call
node.)Buglistvarstore each named variable, with an
initial value of zero.initiallyblock child.blockmoveexpression child,
and "move" this Bug forward (its angle tells
what direction it is facing) by that amount, by setting new values of x
and y. You will need a small amount of
trigonometry to determine the new values of x
and y; get help from a classmate if
necessary. Part
2. The Bug is
supposed to draw a line as it moves (unless its color is set to none).
Create
a Command object that specifies the color and endpoints of the line,
and save
it in a list. Notify the Interpreter that this bug has performed an
action. movetoexpression
children, and set x and y
to these two values, respectively. Part
2. The
Bug is supposed to draw a line as it moves (unless its color is set to
none).
Create a Command object that specifies the color and endpoints of the
line, and
save it in a list. Notify the Interpreter that this bug has performed
an action.turnexpression child,
and add this amount to this Bug's angle. If
necessary, adjust the value to be between 0.0 and 360.0, inclusive.
(Maintain full accuracy--do not use int values!). Part
2. Notify the Interpreter that this bug has
performed an action.turntoexpression child,
and set this Bug's angle to the new value. If
necessary, adjust the value to be between 0.0 and 360.0, inclusive.
(Maintain full accuracy--do not use int values!). Part
2. Notify the Interpreter that this bug has performed an
action.return someExpression
lineassignstore the result of the evaluation
into the variable name.loopblock)
repeatedly. The loop ends when an exit if
statement in the
block is interpreted. You can do it by setting and clearing a boolean
variable, to be checked by block. exitloop.switchcase
child, in order, until one returns "true"--then stop. (It seems strange
to evaluate a case clause, rather than interpreting it, but this is an
easy way to implement the switch statement.) Remember, "false" is any
number between -0.001 and +0.001, and "true" is any number that isn't
false.colorjava.awt.Color
value (there is no shortcut to doing this, you just need a big if
statement), and store the result in this Bug's color
instance variable. Throw some kind of RuntimeException
if the name isn't a legal color.callHashMap<String,Double>,
and put each formal
parameter (under the var node into it. Push
this HashMap onto
this Bug's stack of HashMaps.return
statement, evaluate its expression,
store the result in an instance variable, pop the HashMap off this
Bug's
stack of HashMaps, and return from interpreting the callnode.return
statement, treat it as a return 0 statement.+-*/<, <=,
= (not ==
!), !=, >,
and >=
if statement), and return 1.0
for "true", 0.0 for "false." Remember, two
numbers are "equal" if they are within 0.001 of each other.casecallevaluate
and interpret, not one huge test method for
each. For example, evaluateAddition and interpretAssignmentStatement
(or testAddition and testAssignmentStatement,
or whatever). Remember that JUnit 4 tests can be named whatever you
like.interpret method returns void,
you need to test it by its effect. That means that
pretty much everything you interpret should set the values of some
variables, so you can fetch those variables
and see if they were set correctly.
Zip the complete project and submit it via Blackboard by midnight Tuesday, April 15.