// Interpreter for MiniJS untyped syntax (MiniJS). // Programming Language Technology // Chalmers DAT151, Gothenburg University DIT231 import MiniJS.Absyn.*; public class Interpreter { public Interpreter() {} // Interpreter entry point public void interpret(MiniJS.Absyn.Program prg) { prg.accept(new ExecPrg(), null); } // Execute the program public class ExecPrg implements Program.Visitor { public Void visit(MiniJS.Absyn.Prg prg, Void arg) { Environment env = new Empty(); ExecStm exec = new ExecStm(); for (Stm s: prg.liststm_) env = s.accept(exec, env); return null; } } // Execute statements public class ExecStm implements Stm.Visitor { public Environment visit(MiniJS.Absyn.SAssign p, Environment env) { Value v = p.exp_.accept(new EvalExp(), env); return env.insert(p.ident_, v); } public Environment visit(MiniJS.Absyn.SPrint p, Environment env) { Value v = p.exp_.accept(new EvalExp(), env); v.print(); return env; } } // Evaluate expressions public class EvalExp implements Exp.Visitor { public Value visit(MiniJS.Absyn.EVar p, Environment env) { return env.lookup(p.ident_); } public Value visit(MiniJS.Absyn.EInt p, Environment env) { return new VInt (p.integer_); } public Value visit(MiniJS.Absyn.EDouble p, Environment env) { return new VDouble (p.double_); } public Value visit(MiniJS.Absyn.ETimes p, Environment env) { Value v1 = p.exp_1.accept(new EvalExp(), env); Value v2 = p.exp_2.accept(new EvalExp(), env); return v1.mul(v2); } public Value visit(MiniJS.Absyn.EDiv p, Environment env) { Value v1 = p.exp_1.accept(new EvalExp(), env); Value v2 = p.exp_2.accept(new EvalExp(), env); return v1.div(v2); } public Value visit(MiniJS.Absyn.EPlus p, Environment env) { Value v1 = p.exp_1.accept(new EvalExp(), env); Value v2 = p.exp_2.accept(new EvalExp(), env); return v1.add(v2); } public Value visit(MiniJS.Absyn.EMinus p, Environment env) { Value v1 = p.exp_1.accept(new EvalExp(), env); Value v2 = p.exp_2.accept(new EvalExp(), env); return v1.sub(v2); } } // Environments as linked lists abstract public class Environment { abstract public Value lookup(String x); public Environment insert (String x, Value v) { return new Extend(x, v, this); // no garbage collection } } public class Empty extends Environment { public Empty() {} public Value lookup (String x) { throw new RuntimeException("unbound variable " + x); } } public class Extend extends Environment { final String x; final Value v; final Environment env; public Extend(String x, Value v, Environment env) { this.x = x; this.v = v; this.env = env; } public Value lookup (String y) { if (y.equals(x)) return v; else return env.lookup(y); } } // Values abstract public class Value { abstract public Integer intValue (); abstract public Double doubleValue (); abstract public Value add (Value v); abstract public Value sub (Value v); abstract public Value mul (Value v); abstract public Value div (Value v); abstract public void print(); } public class VInt extends Value { final Integer i; public VInt(Integer i) { this.i = i; } public Integer intValue() { return i; } public Double doubleValue() { return new Double(i); } public Value add (Value v) { if (v instanceof VInt) return new VInt(i + v.intValue()); else return new VDouble(i + v.doubleValue()); } public Value sub (Value v) { if (v instanceof VInt) return new VInt(i - v.intValue()); else return new VDouble(i - v.doubleValue()); } public Value mul (Value v) { if (v instanceof VInt) return new VInt(i * v.intValue()); else return new VDouble(i * v.doubleValue()); } public Value div (Value v) { if (v instanceof VInt) return new VInt(i / v.intValue()); else return new VDouble(i / v.doubleValue()); } public void print() { System.out.println(i); } } public class VDouble extends Value { final Double d; public VDouble(Double d) { this.d = d; } public Double doubleValue() { return d; } public Integer intValue() { throw new RuntimeException("cannot convert Double value to Integer value"); } public Value add (Value v) { return new VDouble(d + v.doubleValue()); } public Value sub (Value v) { return new VDouble(d - v.doubleValue()); } public Value mul (Value v) { return new VDouble(d * v.doubleValue()); } public Value div (Value v) { return new VDouble(d / v.doubleValue()); } public void print() { System.out.println(d); } } }