/**************************************************************************
* MiniPro2: Interpreter for version 2 of a miniature programming language.
*
* COS 126, Princeton University, Fall 2013, Programming Midterm 2 Part 1
*
* Notes: functionally different from MiniPro in step() and isDone();
* has private helper method evaluate(), not part of API.
*
* Dependencies: ST, StdOut
*
* Compilation: javac-introcs MiniPro.java
**************************************************************************/
public class MiniPro2 {
private int pc; // the program counter
private String[][] program; // the program itself
private ST<String, Integer> varTable; // values of all defined variables
// Create interpreter for this program. Don't execute it yet!
public MiniPro2(String[][] program) {
this.program = program;
pc = 0; // line 0 is always the first to execute
varTable = new ST<String, Integer>();
}
// Return the current value of the variable named v. If no
// such variable is currently defined, throw a RuntimeException.
public int valueOf(String v) {
if (!varTable.contains(v))
throw new RuntimeException("Variable named " + v + " not defined");
return varTable.get(v);
}
// Return the number of the line that will execute next.
public int programCounter() {
return pc;
}
// Check if this token is an integer or variable, and give the value
// of it in either case.
private int evaluate(String token) {
// look at token, evaluate it
if (token.matches("[a-z]+")) // it's a variable name
return varTable.get(token);
else // it's an integer
return Integer.parseInt(token);
}
// Execute the line whose number equals the value of the
// program counter. Then, increment the program counter.
public void step() {
String[] line = program[pc]; // current line (1d piece of 2d array)
String command = line[1];
// assignment statement
if (command.equals("=")) {
// look at token on right-hand side, evaluate it
String rhsToken = line[2];
int rhsValue = evaluate(rhsToken);
// save value in variable
varTable.put(line[0], rhsValue);
}
// println statement
else if (command.equals("println")) {
// get value of desired variable, then print it
int value = varTable.get(line[0]);
StdOut.println(value);
}
// mathematical operations
else if (command.equals("+=")) {
// which variable are we updating?
int oldValue = varTable.get(line[0]);
// what should its new value be?
int newValue = oldValue + evaluate(line[2]);
// update
varTable.put(line[0], newValue);
}
else if (command.equals("-=")) {
// which variable are we updating?
int oldValue = varTable.get(line[0]);
// what should its new value be?
int newValue = oldValue - evaluate(line[2]);
// update
varTable.put(line[0], newValue);
}
else if (command.equals("*=")) {
// which variable are we updating?
int oldValue = varTable.get(line[0]);
// what should its new value be?
int newValue = oldValue * evaluate(line[2]);
// update
varTable.put(line[0], newValue);
}
// jump if positive statement
else if (command.equals("pos?jump")) {
// value of variable we are testing
int testValue = evaluate(line[0]);
if (testValue > 0) { // positive?
pc += evaluate(line[2]); // jump!
// return right now so that we don't hit the pc++ line below
return;
}
// else, take no special action
}
// increment the program counter
pc++;
}
// Is the program done?
// For MiniPro2, we have to check not only being at the end,
// but also after the end or before the start.
public boolean isDone() {
return pc >= program.length || pc < 0;
}
}