package org.seqcode.gseutils.expressions; import java.util.*; import java.io.*; public class Evaluator { public static void main(String[] args) { try { eval(); } catch(IOException ie) { ie.printStackTrace(System.err); } } public static void eval() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print(">"); System.out.flush(); String line; Evaluator baseEval = new Evaluator(); while((line = br.readLine()) != null) { ExpressionParser ep = new ExpressionParser(line); List<Expression> lst = ep.getExprList(); for(Expression expr : lst) { Object obj = baseEval.eval(expr); System.out.println(stringify(obj)); } System.out.print(">"); System.out.flush(); } } public static String stringify(Object obj) { if(obj == null) { return "null"; } if(obj instanceof Boolean) { boolean v = ((Boolean)obj).booleanValue(); if(v) { return "#t"; } return "#f"; } return obj.toString(); } private static Map<String,Object> opBindings; static { opBindings = new HashMap<String,Object>(); opBindings.put("+", new Addition()); opBindings.put("-", new Subtraction()); opBindings.put("*", new Multiplication()); opBindings.put("/", new Division()); opBindings.put("=", new Equality()); opBindings.put("!=", new Inequality()); opBindings.put("<", new LessThan()); opBindings.put(">", new GreaterThan()); opBindings.put("car", new Car()); opBindings.put("cdr", new Cdr()); opBindings.put("cons", new Cons()); } private Evaluator parent; private Map<String,Object> bindings; public Evaluator() { parent = null; bindings = new HashMap<String,Object>(); } public Evaluator(Evaluator parent, Vector<String> params, Vector<Object> args) { this.parent = parent; bindings = new HashMap<String,Object>(); for(int i = 0; i < params.size(); i++) { bindings.put(params.get(i), args.get(i)); } } public Object lookup(String name) { if(bindings.containsKey(name)) { return bindings.get(name); } if(parent != null) { return parent.lookup(name); } else { if(opBindings.containsKey(name)) { return opBindings.get(name); } } return null; } public Closure createClosure(CompoundExpression args, Expression body) { return new Closure(this, args, body); } public Object eval(Expression e) { if(e instanceof SimpleExpression) { SimpleExpression se = (SimpleExpression)e; String val = se.getValue(); if(val.equals("null")) { return null; } if(val.equals("#t")) { return Boolean.TRUE; } if(val.equals("#f")) { return Boolean.FALSE; } if(val.matches("-?[0-9]+")) { return new Integer(val); } if(val.matches("-?[0-9]*\\.[0-9]+")) { return new Double(val); } return lookup(val); } else { CompoundExpression ce = (CompoundExpression)e; Expression headExpr = ce.getHead(); List<Expression> argExprs = ce.getArgExprList(); String headString = headExpr.toString(); if(headString.equals("eval")) { Expression ee = argExprs.get(0); Object res = eval(ee); // the following line amounts to an identity function // if the ee is an Expression already, but it converts "lists" // into "Expression"s otherwise, so that something like: // (eval '(+ 1 2)) // works the same as // (eval (cons '+ (cons 1 (cons 2 null)))) Expression arge = ExpressionParser.parseLeadingExpression(Evaluator.stringify(res)); return eval(arge); } if(headString.equals("set!")) { SimpleExpression nameExpr = (SimpleExpression)argExprs.get(0); Object val = eval(argExprs.get(1)); bindings.put(nameExpr.getValue(), val); return null; } if(headString.equals("if")) { Boolean test = (Boolean)eval(argExprs.get(0)); if(test.booleanValue()) { return eval(argExprs.get(1)); } else { return eval(argExprs.get(2)); } } if(headString.equals("quote")) { Expression quotedExpr = argExprs.get(0); return quotedExpr; } if(headString.equals("lambda")) { CompoundExpression larg = (CompoundExpression)argExprs.get(0); Expression barg = argExprs.get(1); return createClosure(larg, barg); } Object headObj = eval(headExpr); Vector<Object> args = new Vector<Object>(); for(Expression arg : argExprs) { args.add(eval(arg)); } if(headObj instanceof Operator) { Operator op = (Operator)headObj; return op.operate(args); } Closure c = (Closure)headObj; Evaluator cEval = c.getEvaluator(); Evaluator lEval = new Evaluator(this, c.getParams(), args); return lEval.eval(c.getBody()); } } } interface SpecialForm { public Object getForm(Evaluator eval, Expression expr); } class QuoteForm implements SpecialForm { public QuoteForm() {} public Object getForm(Evaluator eval, Expression expr) { CompoundExpression ce = (CompoundExpression)expr; Expression arg = ce.getArg(0); if(arg instanceof SimpleExpression) { return arg.toString(); } return new ConsCell((CompoundExpression)arg); } } class LambdaForm implements SpecialForm { public LambdaForm() {} public Object getForm(Evaluator eval, Expression expr) { CompoundExpression ce = (CompoundExpression)expr; SimpleExpression headExpr = (SimpleExpression)ce.getHead(); CompoundExpression args = (CompoundExpression)ce.getArg(0); Expression body = ce.getArg(1); return eval.createClosure(args, body); } } class IfForm implements SpecialForm { public IfForm() {} public Object getForm(Evaluator eval, Expression expr) { CompoundExpression ce = (CompoundExpression)expr; SimpleExpression ifTag = (SimpleExpression)ce.getHead(); Expression test = ce.getArg(0); Expression trueExpr = ce.getArg(1); Expression falseExpr = ce.getArg(2); Object testObj = eval.eval(test); Boolean v = (Boolean)testObj; if(v.booleanValue()) { return eval.eval(trueExpr); } else { return eval.eval(falseExpr); } } } class EvalForm implements SpecialForm { public EvalForm() {} public Object getForm(Evaluator eval, Expression expr) { CompoundExpression ce = (CompoundExpression)expr; Expression arg = ce.getArg(0); Object argValue = eval.eval(arg); String argString = argValue.toString(); Expression parsedExpr = ExpressionParser.parseLeadingExpression(argString); return eval.eval(parsedExpr); } } interface Operator { public Object operate(Vector<Object> args); } class Multiplication implements Operator { public Multiplication() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Integer(i1 * i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Double(i1 * i2); } throw new IllegalArgumentException(); } } class Division implements Operator { public Division() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Integer(i1 / i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Double(i1 / i2); } throw new IllegalArgumentException(); } } class Subtraction implements Operator { public Subtraction() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Integer(i1 - i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Double(i1 - i2); } throw new IllegalArgumentException(); } } class GreaterThan implements Operator { public GreaterThan() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Boolean(i1 > i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Boolean(i1 > i2); } throw new IllegalArgumentException(); } } class LessThan implements Operator { public LessThan() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Boolean(i1 < i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Boolean(i1 < i2); } throw new IllegalArgumentException(); } } class Equality implements Operator { public Equality() {} public Object operate(Vector<Object> args) { return new Boolean(Evaluator.stringify(args.get(0)).equals(Evaluator.stringify(args.get(1)))); } } class Inequality implements Operator { public Inequality() {} public Object operate(Vector<Object> args) { return new Boolean(!Evaluator.stringify(args.get(0)).equals(Evaluator.stringify(args.get(1)))); } } class Addition implements Operator { public Addition() {} public Object operate(Vector<Object> args) { Object a1 = args.get(0), a2 = args.get(1); if(a1 instanceof Integer && a2 instanceof Integer) { int i1 = ((Integer)a1).intValue(), i2 = ((Integer)a2).intValue(); return new Integer(i1 + i2); } if(a1 instanceof Double && a2 instanceof Double) { double i1 = ((Double)a1).doubleValue(), i2 = ((Double)a2).doubleValue(); return new Double(i1 + i2); } throw new IllegalArgumentException(); } } class Cons implements Operator { public Cons() {} public Object operate(Vector<Object> args) { return new ConsCell(args.get(0), args.get(1)); } } class Cdr implements Operator { public Cdr() {} public Object operate(Vector<Object> args) { ConsCell cc = (ConsCell)args.get(0); return cc.getCdr(); } } class Car implements Operator { public Car() {} public Object operate(Vector<Object> args) { ConsCell cc = (ConsCell)args.get(0); return cc.getCar(); } } class ConsCell { private Object car, cdr; public ConsCell(Object head, Object tail) { car = head; cdr = tail; } public ConsCell(CompoundExpression expr) { Expression h = expr.getHead(); if(h instanceof SimpleExpression) { car = ((SimpleExpression)h).getValue(); } else { car = new ConsCell((CompoundExpression)h); } if(expr.getNumArgs() == 0) { cdr = null; } else { cdr = new ConsCell(new CompoundExpression(expr.getArgExprList())); } } public LinkedList asList() { if(cdr == null) { LinkedList l = new LinkedList(); l.addLast(car); return l; } if(!(cdr instanceof ConsCell)) { throw new IllegalArgumentException(); } ConsCell cc = (ConsCell)cdr; LinkedList ll = cc.asList(); ll.addFirst(car); return ll; } public boolean isList() { if(cdr == null) { return true; } if(cdr instanceof ConsCell) { return ((ConsCell)cdr).isList(); } return false; } public Object getCar() { return car; } public Object getCdr() { return cdr; } public String toString() { StringBuilder sb = new StringBuilder(); if(isList()) { LinkedList ll = asList(); int i = 0; sb.append("("); for(Object o : ll) { sb.append(Evaluator.stringify(o)); if(i < ll.size()-1) { sb.append(" "); } i++; } sb.append(")"); return sb.toString(); } sb.append("("); sb.append(Evaluator.stringify(car)); sb.append(" . "); sb.append(Evaluator.stringify(cdr)); sb.append(")"); return sb.toString(); } } class Closure { private Vector<String> params; private Evaluator env; private Expression body; public Closure(Evaluator env, CompoundExpression p, Expression b) { this.env = env; params = new Vector<String>(); Set<String> paramSet = new HashSet<String>(); for(Expression e : p.getExprs()) { SimpleExpression se = (SimpleExpression)e; if(!paramSet.contains(se.getValue())) { params.add(se.getValue()); } } body = b; } public Vector<String> getParams() { return params; } public Expression getBody() { return body; } public Evaluator getEvaluator() { return env; } }