public interface Env { Env nullEnv(); Env extend(String var, Val value); Val lookup(String var); String toString(); } /* **************************************************************** */ public interface Val { String toString(); } public class IntVal implements Val { int value; IntVal(int value) { this.value = value; } public String toString() { return "" + value; } } public class Closure implements Val { Env env; LamForm<Val> fun; Closure(LamForm<Val> fun, Env env) { this.fun = fun; this.env = env; } public String toString() { return "<CLOSURE: " + env + " | " + fun + ">"; } } /* **************************************************************** */ public interface LangProcessor<Result> { Result constCase(ConstForm<Result> cf); Result varCase(VarForm<Result> vf); Result lamCase(LamForm<Result> lf); Result appCase(AppForm<Result> af); } public class Interp implements LangProcessor<Val> { Env env; Interp(Env env) { this.env = env; } public Val constCase(ConstForm<Val> cf) { return new IntVal(cf.value); } public Val varCase(VarForm<Val> vf) { return env.lookup(vf.name); } public Val lamCase(LamForm<Val> lf) { return new Closure<LangProcessor<Val>>(lf, env); } public Val appCase(AppForm<Val> af) { Val rator = af.fun.process(this); Val rand = af.arg.process(this); if (rator instanceof Closure) { Closure clos = (Closure) rator; LamForm<Val> lf = clos.fun; Env newEnv = clos.env.extend(lf.var, rand); LangProcessor<Val> newProc = new Interp(newEnv); return lf.body.process(newProc); } else { throw new ApplicationException("not a function: " + rator); } } } /* **************************************************************** */ public interface Form<Result> { Result process(LangProcessor<Result> lp); String toString(); } public class ConstForm<R> implements Form<R> { int value; ConstForm(int value) { this.value = value; } public R process(LangProcessor<R> lp) { return lp.constCase(this); } public String toString() { return "" + value; } } public class VarForm<R> implements Form<R> { String name; VarForm(String name) { this.name = name; } public R process(LangProcessor<R> lp) { return lp.varCase(this); } public String toString() { return name; } } public class LamForm<R> implements Form<R> { String var; Form<R> body; LamForm(String var, Form<R> body) { this.var = var; this.body = body; } public R process(LangProcessor<R> lp) { return lp.lamCase(this); } public String toString() { return "\\" + var + ".(" + body + ")"; } } public class AppForm<R> implements Form<R> { Form<R> fun, arg; AppForm(Form<R> fun, Form<R> arg) { this.fun = fun; this.arg = arg; } public R process(LangProcessor<R> lp) { return lp.appCase(this); } public String toString() { return "(" + fun + " " + arg + ")"; } }