package funjay.astvisitor; import funjay.abssyntree.*; import java.util.*; public class InterpretingVisitor extends DepthFirstVisitor { private int result; private boolean boolResult() { return result != 0; } private void setBoolResult(boolean b) { result = b? 1 : 0; } private HashMap gammaG; private HashMap gammaM; // mu stores expressions, not values private Expression[] mu; private int a; // when we look something up, we need to evaluate the expression private int sigma(String id) { mu[gammaM.get(id)].accept(this); return result; } // a method to store expressions private void sigmaU(String id, Expression e) { mu[gammaM.get(id)] = e; } // for convenience, if we do want to store integers, convert them to literal expressions private void sigmaU(String id, int val) { mu[gammaM.get(id)] = new IntLitExpr(new IntLiteral(val)); } private void allocate(Iterator ids) { for (; ids.hasNext(); ) gammaM.put(ids.next().getValue(), ++a); } private void deallocate(Iterator ids) { for (; ids.hasNext(); ) { a--; gammaM.remove(ids.next().getValue()); } } private HashMap> paramMap; private HashMap bodyMap; public void visit(Program n) { mu = new Expression[1024]; a = 0; // This is a bit of a hack. Declaration is hard-wired to // add to gammaM, but this time we want it to populate // gammaG. So, we just copy gammaM to gammaG when // it's done. gammaM = new HashMap(); addDecl = true; for (Iterator it = n.f0(); it.hasNext(); ) it.next().accept(this); gammaG = (HashMap) gammaM.clone(); paramMap = new HashMap>(); bodyMap = new HashMap(); for (Iterator it = n.f1(); it.hasNext(); ) it.next().accept(this); n.f2().accept(this); } private boolean addDecl; public void visit(Declaration n) { if (addDecl) allocate(n.f1()); else deallocate(n.f1()); } // When we visit methods and their parameters, it's not to // interpret them but to populate the paramMap and bodyMap. private Vector currentParams; public void visit(Method n) { currentParams = new Vector(); for (Iterator it = n.f2(); it.hasNext(); ) it.next().accept(this); paramMap.put(n.f1().getValue(), currentParams); bodyMap.put(n.f1().getValue(), n.f3()); } public void visit(Parameter n) { currentParams.add(n.f1()); } // skip can be inherited from DepthFirstVisitor. public void visit(Block n) { addDecl = true; for (Iterator it = n.f0(); it.hasNext(); ) it.next().accept(this); for (Iterator it = n.f1(); it.hasNext(); ) it.next().accept(this); addDecl = false; for (Iterator it = n.f0(); it.hasNext(); ) it.next().accept(this); } public void visit(Assignment n) { n.f1().accept(this); sigmaU(n.f0().getValue(), result); } public void visit(Conditional n) { n.f0().accept(this); if (boolResult()) n.f1().accept(this); else n.f2().accept(this); } public void visit(Loop n) { for (;;) { n.f0().accept(this); if (! boolResult()) break; n.f1().accept(this); } } public void visit(Print n) { n.f0().accept(this); System.out.println(result); } public void visit(CallStmt n) { // evaluate the actual parameters /* Vector actuals = new Vector(); for (Iterator it = n.f1(); it.hasNext(); ) { it.next().accept(this); actuals.add(result); } */ // No, don't evaluate the actual parameters. Just collect the expressions. Vector actuals = new Vector(); for (Iterator it = n.f1(); it.hasNext(); ) { actuals.add(it.next()); } // set up the new environment, starting from the globals // and adding the formal parameters HashMap gammaT = gammaM; gammaM = (HashMap) gammaG.clone(); Vector formals = paramMap.get(n.f0().getValue()); allocate(formals.iterator()); Iterator formIt = formals.iterator(); // store the actual expressions, not their values, in the parameters //for (Iterator actIt = actuals.iterator(); for (Iterator actIt = actuals.iterator(); actIt.hasNext() && formIt.hasNext(); ) sigmaU(formIt.next().getValue(), actIt.next()); // "call" the funtion bodyMap.get(n.f0().getValue()).accept(this); // deallocate and restore deallocate(formals.iterator()); gammaM = gammaT; } public void visit(Return n) { n.f0().accept(this); } public void visit(Variable n) { result = sigma(n.f0().getValue()); } public void visit(IntLitExpr n) { result = n.f0().getValue(); } public void visit(BoolLitExpr n) { setBoolResult(n.f0().getValue()); } public void visit(BinaryExpr n) { n.f0().accept(this); String op = n.f1().getValue(); if (op.equals("+")) { int operand1 = result; n.f2().accept(this); result = operand1 + result; } if (op.equals("-")) { int operand1 = result; n.f2().accept(this); result = operand1 - result; } if (op.equals("*")) { int operand1 = result; n.f2().accept(this); result = operand1 * result; } if (op.equals("/")) { int operand1 = result; n.f2().accept(this); result = operand1 / result; } if (op.equals("&&")) { boolean operand1 = boolResult(); n.f2().accept(this); setBoolResult(operand1 && boolResult()); } if (op.equals("||")) { boolean operand1 = boolResult(); n.f2().accept(this); setBoolResult(operand1 || boolResult()); } if (op.equals("==")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 == result); } if (op.equals("!=")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 != result); } if (op.equals("<=")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 <= result); } if (op.equals(">=")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 >= result); } if (op.equals("<")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 < result); } if (op.equals(">")) { int operand1 = result; n.f2().accept(this); setBoolResult(operand1 > result); } } public void visit(UnaryExpr n) { n.f1().accept(this); setBoolResult(!boolResult()); } public void visit(Call n) { // evaluate the actual parameters Vector actuals = new Vector(); for (Iterator it = n.f1(); it.hasNext(); ) { it.next().accept(this); actuals.add(result); } // set up the new environment, starting from the globals // and adding the formal parameters HashMap gammaT = gammaM; gammaM = (HashMap) gammaG.clone(); Vector formals = paramMap.get(n.f0().getValue()); allocate(formals.iterator()); Iterator formIt = formals.iterator(); for (Iterator actIt = actuals.iterator(); actIt.hasNext() && formIt.hasNext(); ) sigmaU(formIt.next().getValue(), actIt.next()); // "call" the funtion bodyMap.get(n.f0().getValue()).accept(this); // deallocate and restore deallocate(formals.iterator()); gammaM = gammaT; } }