Skip to content

Instantly share code, notes, and snippets.

@dvanhorn
Last active August 29, 2015 14:18
Show Gist options
  • Save dvanhorn/987c145670e5103cba6f to your computer and use it in GitHub Desktop.
Save dvanhorn/987c145670e5103cba6f to your computer and use it in GitHub Desktop.
defun interp in Java
interface Exp {
<A> A visit(ExpVisitor<A> v);
}
interface Val {
<A> A visit(ValVisitor<A> v);
}
abstract class Env {
public Env extend(String x, Val v) {
return new Ext(x, v, this);
}
abstract public Val lookup(String x);
}
class Mt extends Env {
Mt() {}
public Val lookup(String x) {
throw new RuntimeException("No such binding");
}
}
class Ext extends Env {
String x;
Val v;
Env r;
Ext(String x, Val v, Env r) {
this.x = x;
this.v = v;
this.r = r;
}
public Val lookup(String y) {
return y.equals(this.x) ?
this.v : this.r.lookup(y);
}
}
interface ExpVisitor<A> {
A var(String x);
A num(Integer n);
A app(Exp e1, Exp e2);
A lam(String x, Exp e);
}
interface ValVisitor<A> {
A clos(String x, Exp e, Env r);
A num(Integer n);
}
class Var implements Exp {
String x;
Var(String x) {
this.x = x;
}
public <A> A visit(ExpVisitor<A> v) {
return v.var(this.x);
}
}
class Num implements Exp, Val {
Integer n;
Num(Integer n) {
this.n = n;
}
public <A> A visit(ExpVisitor<A> v) {
return v.num(this.n);
}
public <A> A visit(ValVisitor<A> v) {
return v.num(this.n);
}
}
class Lam implements Exp {
String x;
Exp e;
Lam(String x, Exp e) {
this.x = x;
this.e = e;
}
public <A> A visit(ExpVisitor<A> v) {
return v.lam(this.x, this.e);
}
}
class App implements Exp {
Exp e1;
Exp e2;
App(Exp e1, Exp e2) {
this.e1 = e1;
this.e2 = e2;
}
public <A> A visit(ExpVisitor<A> v) {
return v.app(this.e1, this.e2);
}
}
class Clos implements Val {
String x;
Exp e;
Env r;
Clos(String x, Exp e, Env r) {
this.x = x;
this.e = e;
this.r = r;
}
public <A> A visit(ValVisitor<A> v) {
return v.clos(this.x, this.e, this.r);
}
}
// The eval "function"
class Eval implements ExpVisitor<Val> {
Env r;
Eval(Env r) {
this.r = r;
}
public Val var(String x) { return this.r.lookup(x); }
public Val num(Integer n) { return new Num(n); }
public Val app(Exp e1, Exp e2) {
return e1.visit(this).visit(new Apply(e2.visit(this)));
}
public Val lam(String x, Exp e) {
return new Clos(x, e, this.r);
}
}
// The apply "function"
class Apply implements ValVisitor<Val> {
Val a;
Apply(Val a) {
this.a = a;
}
public Val num(Integer n) { throw new RuntimeException("Applied a non-function"); }
public Val clos(String x, Exp e, Env r) {
return e.visit(new Eval(r.extend(x, this.a)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment