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 + ")";
}
}