継続可能なインタプリタ
スピードとかはぜんぜん考えてませんけど、nagasimaさんが言っていたツリーをたどる、
継続可能なインタプリタを作ってみました。
足し算しかできないけどこんな感じなのかなっと。
import java.util.Hashtable; class t{ public static void main(String argv[]) { Atom exp = new Add(new Number(5), new Add(new CC(new Number(1)), new Number(2))); System.out.println(exp = Atom.e(exp)); System.out.println(exp = Atom.e(exp)); } } class Atom { static Atom e(Atom a) { Context context = new Context(); try { return a.eval(context); } catch (CCException e) { e.cc.context = context; e.cc.root = a; return e.cc; } } Atom eval(Context c) throws CCException { return null;} } class Number extends Atom { int data; Number(int i) { data = i;} Atom eval(Context c) throws CCException { return this;} public String toString() { return ""+data; } } class Add extends Atom { Atom l; Atom r; Add(Atom l, Atom r) { this.l = l; this.r = r; } Atom eval(Context c) throws CCException { switch(c.pc) { case 0: c.child = new Context(); c.pc++; case 1: c.env.put("x", l.eval(c.child)); c.child = new Context(); c.pc++; case 2: c.env.put("y", r.eval(c.child)); c.pc++; } return new Number( ((Number)c.env.get("x")).data + ((Number)c.env.get("y")).data); } } class Context { int pc = 0; Context child; Hashtable env = new Hashtable(); } class CCException extends Exception { CC2 cc; CCException(CC2 cc) { this.cc = cc; } } class CC extends Atom { Atom data; CC(Atom data) { this.data = data; } Atom eval(Context c) throws CCException { switch(c.pc) { case 0: c.pc++; throw new CCException(new CC2()); } return data; } } class CC2 extends Atom{ Atom root; Context context; Atom eval(Context c) throws CCException { return root.eval(context); } }