module Large = struct type exp = Var of string | Lam of string*exp | Apply of exp * exp exception BadExp let subst e1_with e2_for x = failwith "unimplemented" let rec interp_large e = match e with Var _ -> raise BadExp(*unbound variable*) | Lam _ -> e (*functions are values*) | Apply(e1,e2) -> let v1 = interp_large e1 in let v2 = interp_large e2 in match v1 with Lam(x,e3) -> interp_large (subst e3 v2 x) | _ -> failwith "impossible" (* why? *) let rec interp_large2 e = match e with Var _ -> raise BadExp(*unbound variable*) | Lam _ -> e (*functions are values*) | Apply(e1,e2) -> let v1 = interp_large2 e1 in (* we used to evaluate e2 to v2 here *) match v1 with Lam(x,e3) -> interp_large2 (subst e3 e2 x) | _ -> failwith "impossible" (* why? *) end module Env = struct type exp = Var of string | Lam of string * exp | Apply of exp * exp | Closure of string * exp * env and env = (string * exp) list let rec interp env e = match e with Var s -> List.assoc s env (* do the lookup *) | Lam(s,e2) -> Closure(s,e2,env) (*store env!*) | Closure _ -> e (* closures are values *) | Apply(e1,e2) -> let v1 = interp env e1 in let v2 = interp env e2 in match v1 with Closure(s,e3,env2) -> interp((s,v2)::env2) e3 | _ -> failwith "impossible" end module Small = struct type exp = V of string | L of string*exp | A of exp * exp let subst e1_with e2_for x = failwith "unimplemented" let rec interp_one e = match e with V _ -> failwith "interp_one" (*unbound var*) | L _ -> failwith "interp_one" (*already done*) | A(L(s1,e1),L(s2,e2)) -> subst e1 (L(s2,e2)) s1 | A(L(s1,e1),e2) -> A(L(s1,e1),interp_one e2) | A(e1,e2) -> A(interp_one e1, e2) let rec interp_small e = match e with V _ -> failwith "interp_small" (*unbound var*) | L _ -> e | A(e1,e2) -> interp_small (interp_one e) end module Ctxt = struct type exp = V of string | L of string*exp | A of exp * exp let subst e1_with e2_for x = failwith "unimplemented" type ectxt = Hole | Left of ectxt * exp | Right of exp * ectxt (*exp a value*) let rec split e = match e with A(L(s1,e1),L(s2,e2)) -> (Hole,e) | A(L(s1,e1),e2) -> let (ctx2,e3) = split e2 in (Right(L(s1,e1),ctx2), e3) | A(e1,e2) -> let (ctx2,e3) = split e1 in (Left(ctx2,e2), e3) | _ -> failwith "bad args to split" let rec fill (ctx,e) = (* plug the hole *) match ctx with Hole -> e | Left(ctx2,e2) -> A(fill (ctx2,e), e2) | Right(e2,ctx2) -> A(e2, fill (ctx2,e)) let rec interp_small e = match e with V _ -> failwith "interp_small" (*unbound var*) | L _ -> e | A(_,_) -> match split e with (ctx, A(L(s3,e3),v)) -> interp_small(fill(ctx, subst e3 v s3)) | _ -> failwith "bad split" end module Continuations = struct type exp = V of string | L of string*body | A of exp * exp | Letcc of string * exp and body = Exp of exp | Ctxt of ectxt and ectxt = Hole | Left of ectxt * exp | Right of exp * ectxt (*exp a value*) let subst e1_with e2_for x = failwith "unimplemented" let rec split e = match e with A(L(s1,e1),L(s2,e2)) -> (Hole,e) | Letcc(s1,e1) -> (Hole,e) | A(L(s1,e1),e2) -> let (ctx2,e3) = split e2 in (Right(L(s1,e1),ctx2), e3) | A(e1,e2) -> let (ctx2,e3) = split e1 in (Left(ctx2,e2), e3) | _ -> failwith "bad args to split" let rec fill (ctx,e) = (* plug the hole *) match ctx with Hole -> e | Left(ctx2,e2) -> A(fill (ctx2,e), e2) | Right(e2,ctx2) -> A(e2, fill (ctx2,e)) let rec interp_small e = match e with V _ -> failwith "interp_small" (*unbound var*) | L _ -> e | _ -> match split e with (ctx, A(L(s3,Exp e3),v)) -> interp_small(fill(ctx, subst e3 v s3)) | (ctx, A(L(s3,Ctxt c3),v)) -> (* not really a lambda! *) interp_small(fill(c3, v)) (* woah *) | (ctx, Letcc(s3,e3)) -> interp_small(fill(ctx, subst e3 (L("",Ctxt ctx)) s3)) (* woah *) | _ -> failwith "bad split" end