// Semantics.java // // This file is from Tucker and Noonan's web site (Appendix B and Chapter 4), // except that the following changes have been made: // (1) Modifications to take advantage of the use of Java Generics in the // AbstractSyntax.java file from the previous labs. // (2) Modification of State to also use Java Generics. // (3) Modification of State's onion method to return a new State rather than // mutating the existing one. // (4) Addition of a main method to run the interpreter. import java.util.*; import java.io.IOException; class State extends Hashtable { // Defines the set of variables and their associated values // that are active during interpretation: State is implemented as // a Java Hashtable. // construct the empty state public State() { } // construct a new state with a single key-value pair public State(Variable key, Value val) { put(key, val); } // Overriding union function "onion" on this State and t; // returns a State composed of all elements in t together // with all elements in this State that are not in t. public State onion (State t) { State result = new State(); result.putAll(this); result.putAll(t); return result; } public void display () { System.out.print("{ "); for (Enumeration e = keys(); e.hasMoreElements(); ) { Variable key = e.nextElement(); Value val = get(key); System.out.print("<" + key.id + ", "); if (val.type.isInteger()) System.out.print (val.intValue + ">"); else if (val.type.isBoolean()) System.out.print (val.boolValue + ">"); else System.out.print ("undefined>"); if (e.hasMoreElements()) System.out.print(", "); } System.out.println(" }"); } } // Following is the semantics class, characterized by the meaning // function M and its auxiliary function applyBinary. public class Semantics { State M (Program p) { return M (p.body, initialState(p.decpart)); } State initialState (Declarations d) { State sigma = new State(); Value undef = new Value(); for (int i = 0; i < d.size(); i++) sigma.put(d.elementAt(i).v, undef); return sigma; } Value applyBinary (Operator op, Value v1, Value v2) { if (v1.type.isUndefined() || v2.type.isUndefined()) { return new Value(); } else if (op.ArithmeticOp( )) { if (op.val.equals(Operator.PLUS)) return new Value(v1.intValue + v2.intValue); if (op.val.equals(Operator.MINUS)) return new Value(v1.intValue - v2.intValue); if (op.val.equals(Operator.TIMES)) return new Value(v1.intValue * v2.intValue); if (op.val.equals(Operator.DIV)) return new Value(v1.intValue / v2.intValue); } else if (op.RelationalOp( )) { if (op.val.equals(Operator.LT)) return new Value(v1.intValue < v2.intValue); if (op.val.equals(Operator.LE)) return new Value(v1.intValue <= v2.intValue); if (op.val.equals(Operator.EQ)) return new Value(v1.intValue == v2.intValue); if (op.val.equals(Operator.NE)) return new Value(v1.intValue != v2.intValue); if (op.val.equals(Operator.GE)) return new Value(v1.intValue >= v2.intValue); if (op.val.equals(Operator.GT)) return new Value(v1.intValue > v2.intValue); } else if (op.BooleanOp( )) { if (op.val.equals(Operator.AND)) return new Value(v1.boolValue && v2.boolValue); if (op.val.equals(Operator.OR)) return new Value(v1.boolValue || v2.boolValue); } return null; } Value applyUnary (Operator op, Value v) { if (v.type.isUndefined()) return new Value(); else if (op.val.equals("!")) return new Value(!v.boolValue); return null; } Value M (Expression e, State sigma) { if (e instanceof Value) return (Value)e; if (e instanceof Variable) if (!sigma.containsKey((Variable)e)) return new Value(); else return sigma.get((Variable)e); if (e instanceof Binary) return applyBinary (((Binary)e).op, M(((Binary)e).term1, sigma), M(((Binary)e).term2, sigma)); if (e instanceof Unary) return applyUnary(((Unary)e).op, M(((Unary)e).term, sigma)); return null; } State M (Statement s, State sigma) { if (s instanceof Skip) return M((Skip)s, sigma); if (s instanceof Assignment) return M((Assignment)s, sigma); if (s instanceof Conditional) return M((Conditional)s, sigma); if (s instanceof Loop) return M((Loop)s, sigma); if (s instanceof Block) return M((Block)s, sigma); return null; } State M (Skip s, State sigma) { return sigma; } State M (Assignment a, State sigma) { return sigma.onion(new State(a.target, M (a.source, sigma))); } State M (Block b, State sigma) { for (int i=0; i