Last active
August 29, 2015 14:18
-
-
Save dvanhorn/005d3b5f5791f97d7864 to your computer and use it in GitHub Desktop.
Definitional interp without closures in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Exp { | |
<A> A visit(ExpVisitor<A> v); | |
} | |
interface Val { | |
Val apply(Val a); | |
Integer n(); | |
} | |
abstract class AVal implements Val { | |
public Val apply(Val a) { | |
throw new RuntimeException("Not a function"); | |
} | |
public Integer n() { | |
throw new RuntimeException("Not a number"); | |
} | |
} | |
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); | |
A ifz(Exp e1, Exp e2, Exp e3); | |
} | |
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 extends AVal implements Exp, Val { | |
Integer n; | |
Num(Integer n) { | |
this.n = n; | |
} | |
public <A> A visit(ExpVisitor<A> v) { | |
return v.num(this.n); | |
} | |
public Integer n() { return this.n; } | |
public String toString() { return this.n.toString(); } | |
} | |
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 If implements Exp { | |
Exp e1; | |
Exp e2; | |
Exp e3; | |
If(Exp e1, Exp e2, Exp e3) { | |
this.e1 = e1; | |
this.e2 = e2; | |
this.e3 = e3; | |
} | |
public <A> A visit(ExpVisitor<A> v) { | |
return v.ifz(this.e1, this.e2, this.e3); | |
} | |
} | |
// 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).apply(e2.visit(this)); | |
} | |
public Val lam(String x, Exp e) { | |
return new AVal() { | |
public Val apply(Val a) { | |
return e.visit(new Eval(r.extend(x,a))); | |
} | |
}; | |
} | |
public Val ifz(Exp e1, Exp e2, Exp e3) { | |
return e1.visit(this).n().equals(0) ? e2.visit(this) : e3.visit(this); | |
} | |
} | |
class Interp { | |
public static void main(String[] xs) { | |
Val sub1 = | |
new AVal() { | |
public Val apply(Val n) { | |
return new AVal() { | |
public Integer n() { return n.n() - 1; } | |
}; | |
} | |
}; | |
Val times = | |
new AVal() { | |
public Val apply(Val n) { | |
return new AVal() { | |
public Val apply(Val m) { | |
return new Num(n.n() * m.n()); | |
}; | |
}; | |
} | |
}; | |
// Y combinator | |
Exp y1 = | |
new Lam("x", | |
new App(new Var("f"), | |
new Lam("y", | |
new App(new App(new Var("x"), | |
new Var("x")), | |
new Var("y"))))); | |
Exp rec = | |
new Lam("f", new App(y1, y1)); | |
Exp fact = | |
new App(rec, | |
new Lam("fact", | |
new Lam("n", | |
new If(new Var("n"), | |
new Num(1), | |
new App(new App(new Var("times"), | |
new Var("n")), | |
new App(new Var("fact"), | |
new App(new Var("sub1"), | |
new Var("n")))))))); | |
Env r = new Ext("sub1", sub1, new Ext("times", times, new Mt())); | |
System.out.println(new App(fact, new Num(5)).visit(new Eval(r))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment