| CIT
594 Assignment
8: Robot Interpreter, part 2 Spring 2007, David Matuszek |
You have now written a Parser for a fairly simple programming language (RoboTalk), and an Interpreter for most of the language. This assignment concludes the implementation of the language.
Programs in RoboTalk consist of a main program, which is just a list of commands,
followed by some number of methods, each of which begins with the keyword
define and ends with the keyword end.
For your main program you used a Map (probably a HashMap) to keep track of
the values of variables. The rules were these:
map.put(variable, value) into your map. You did not evaluate
the variable on the left-hand side of the assignment statement.value
= map.get(variable) to get its value.put it in with a value
of zero, and used zero as its value. In this assignment you will implement methods, and you will need to be concerned about the scope of variables. Unlike Java, which has static scope (you can tell what method owns a variable by just looking at where it is declared), RoboTalk will have dynamic scope (variables belong to the method in which they are first used).
Before you begin to interpret your program, do the following.
Create a new Map to keep track of your methods. This Map is different from
all the rest of the Maps in your program; its keys will be the names
of methods, and its values will be (references to) the actual Tree
(under program
-> procedures) in the complete parse tree. Step through the parse
tree and populate (put keys and values in) this Map.
Later on, when you need to call a method, just look it up in this Map, handle parameter transmission (see below), and interpret the body of the method.
Your basic data structure for dealing with variables will
be a stack
of maps; specifically, a Stack<Map<String,Integer>>.
Name this stack variables, and do not make it private. The Map that you used
for variables in your main program will be the first (bottommost) thing
on this stack. (Note: Stack extends Vector,
and you will almost certainly need to use one or more Vector operations;
but most of the time, think of this as just a Stack.)
Each time you call a method, you create a new Map and put it on the stack. This Map is used to hold the variables (and their values) that are "owned" by this method. If the method recurs (calls itself), create a new Map for each level of the recursion.
When you call a method, do the following:
define).When you need to fetch the value of a variable, do the following:
put it in the topmost Map
with a value of zero, and use zero as its value.When you need to store the value of a variable, do the following:
put its new value there.put its value in the topmost Map. When you return from a method, pop its Map from the stack. (But
before you do this, evaluate the expression that is to be returned and put
it in a safe place--if the method was called from within an expression, you
will need this value in the calling expression.)
Here are at least some of the consequences of this particular way of doing dynamic scope:
Program skeleton Explanation define A use var call B end define B use var endMethod B uses the variable varthat was first used in Adefine A call B use var end define B use var endMethod B uses its own var, then returns. Since B's Map is discarded when it returns, method A uses a new, differentvar.use var1 call A use var2 define A use var1 use var2 endThe main program uses var1, but doesn't usevar2, before it calls method A. Hence, method A uses the samevar1as the main program, but uses its ownvar2.if 2 = 2 { use var1 } else { use var2 } call A define A use var1 use var2 endJust as in the previous example, the main program uses var1but doesn't usevar2before it calls method A. Hence, method A uses the samevar1as the main program, but uses its ownvar2.define A use var call B 5 end define B var use var endSince varis a formal parameter of method B, it hides the variable of the same name in method A. There are two distinct variables namedvar.
Test your interpreter with some RoboTalk programs (written as Strings in your
test class). Make sure that you can pass values in to methods and get the
correct value back. Also devise a couple of simple test programs to ensure
that you have implemented the dynamic scope rules correctly (to simplify
testing, your variables stack should not be private).
Zip the complete Eclipse project and submit via Blackboard before
midnight Thursday, April 12 Sunday, April 15.