infixr ->> ::
datasort ty = int | ->> of (ty, ty) | bot | cont of ty
datasort env = nil | :: of (ty, env)
datatype VAR (env, ty) =
| {G:env} {t:ty} VARone (t :: G, t)
| {G:env} {t1,t2:ty} VARshi (t2 :: G, t1) of VAR (G, t1)
fun nat_of_var {G:env} {t:ty} (x: VAR (G, t)): Nat =
case+ x of VARone () => 1 | VARshi x => 1 + nat_of_var x
datatype EXP (env, ty) =
| {G:env} {t:ty} EXPvar (G, t) of VAR (G, t)
| {G:env} {t1,t2:ty} EXPlam (G, t1 ->> t2) of EXP (t1 :: G, t2)
| {G:env} {t1,t2:ty} EXPapp (G, t2) of (EXP (G, t1 ->> t2), EXP (G, t1))
| {G:env} {t1,t2:ty} EXPlet (G, t2) of (EXP (G, t1), EXP (t1 :: G, t2))
| {G:env} {t:ty} EXPcal (G, t) of EXP (G, cont(t) ->> t)
| {G:env} {t1,t2:ty} EXPthr (G, t2) of (EXP (G, cont t1), EXP (G, t1))
typedef EXP0 (t: ty) = EXP (nil, t)
dataprop RT1 (ty, ty, int) =
| {t,t':ty} {n:nat} RT1 (t, (t' ->> bot) ->> bot, n+1) of RT2 (t, t', n)
and RT2 (ty, ty, int) =
| RT2int (int, int, 0)
| {t1,t2,t1',t2':ty} {n1,n2:nat}
RT2fun (t1 ->> t2, t1' ->> t2',n1+n2+1) of (RT2(t1, t1',n1), RT1 (t2, t2',n2))
| RT2bot (bot, bot, 0)
| {t,t':ty} {n:nat} RT2cont(cont(t), t' ->> bot,n+1) of RT2 (t, t',n)
propdef RT10 (t1: ty, t2: ty) = [n:nat] RT1 (t1, t2, n)
propdef RT20 (t1: ty, t2: ty) = [n:nat] RT2 (t1, t2, n)
extern prval rt1fun: {t:ty} () -<> [t':ty] RT10 (t, t')
extern prval rt2fun: {t1:ty} () -<> [t2:ty] RT20 (t1, t2)
dataprop TYEQ (ty, ty) = {t:ty} TYEQ (t, t)
prfun rt1eq {t,t1,t2:ty} {n1,n2:nat} .<n1>.
(pf1: RT1 (t, t1, n1), pf2: RT1 (t, t2, n2))
:<> TYEQ (t1, t2) = begin case+ (pf1, pf2) of
(RT1 pf1, RT1 pf2) => let prval TYEQ () = rt2eq (pf1, pf2) in TYEQ end
end
and rt2eq {t,t1,t2:ty} {n1,n2:nat} .<n1>.
(pf1: RT2 (t, t1, n1), pf2: RT2 (t, t2, n2)):<> TYEQ (t1, t2) = begin
case+ (pf1, pf2) of
| (RT2int (), RT2int ()) => TYEQ
| (RT2fun (pf11, pf12), RT2fun (pf21, pf22)) => let
prval TYEQ () = rt2eq (pf11, pf21) and TYEQ () = rt1eq (pf12, pf22)
in
TYEQ ()
end
| (RT2cont pf1, RT2cont pf2) => begin
let prval TYEQ () = rt2eq (pf1, pf2) in TYEQ () end
end
| (RT2bot (), RT2bot ()) => TYEQ ()
end
datatype EXP' (env, ty) =
| {G:env} {t:ty} EXPvar' (G, t) of VAR (G, t)
| {G:env} {t1,t2:ty} EXPlam' (G, t1 ->> t2) of EXP' (t1 :: G, t2)
| {G:env} {t1,t2:ty} EXPapp' (G, t2) of (EXP' (G, t1 ->> t2), EXP' (G, t1))
| {G:env} {t1,t2:ty} EXPlet' (G, t2) of (EXP' (G, t1), EXP' (t1 :: G, t2))
typedef EXP0' (t:ty) = EXP' (nil, t)
typedef SUB (G1:env, G2:env) = {t:ty} VAR(G1,t) -> EXP' (G2,t)
extern fun print_exp1 {G:env} {t:ty} (e0: EXP' (G, t)): void
overload print with print_exp1
implement print_exp1 e0 = begin case+ e0 of
| EXPvar' x => let
val n = nat_of_var x
in
print "EXPvar' ("; print n; print ")"
end
| EXPlam' e => begin
print "EXPlam' ("; print_exp1 e; print ")"
end
| EXPapp' (e1, e2) => begin
print "EXPapp' ("; print_exp1 e1; print ", "; print_exp1 e2; print ")"
end
| EXPlet' (e1, e2) => begin
print "EXPlet' ("; print_exp1 e1; print ", "; print_exp1 e2; print ")"
end
end
val idSub = (lam x => EXPvar' x)
: {G:env} SUB (G, G)
val shiSub = (lam x => EXPvar' (VARshi x))
: {G:env} {t:ty} SUB (G, t :: G)
fun subst {G1,G2:env} {t:ty}
(sub: SUB(G1,G2)) (e: EXP' (G1,t))
: EXP' (G2,t) = begin case+ e of
| EXPvar' x => sub (x)
| EXPlam' e => EXPlam' (subst (subLam sub) e)
| EXPapp' (e1, e2) => EXPapp' (subst sub e1, subst sub e2)
| EXPlet' (e1, e2) => EXPlet' (subst sub e1, subst (subLam sub) e2)
end
and subLam {G1,G2:env} {t:ty}
(sub: SUB (G1,G2)): SUB (t::G1,t::G2) = begin
lam x => case+ x of
| VARone () => EXPvar' (VARone)
| VARshi x' => subst (shiSub {..} {..}) (sub x')
end
fn EXPone1 {G:env} {t:ty} (): EXP' (t :: G, t) = EXPvar' (VARone)
fn EXPtwo1 {G:env} {t1,t2:ty} (): EXP' (t1 :: t2 :: G, t2) =
EXPvar' (VARshi VARone)
fn expShi {G:env} {t1,t2:ty} (e: EXP' (G, t1)): EXP' (t2 :: G, t1) =
subst (shiSub {..} {..}) e
typedef VM (G1: env, G2: env) =
{t1:ty} VAR (G1, t1) -> [t2: ty] (RT20 (t1, t2) | VAR (G2, t2))
val vmNil =
(lam x => case+ x of VARone _ =/=> () | VARshi _ =/=> ())
: VM (nil, nil)
fn vmShi {G1,G2:env} {t:ty} (vm: VM (G1, G2)) =
(lam x1 => let val (pf | x2) = vm x1 in (pf | VARshi x2) end)
: VM (G1, t :: G2)
fn vmLam {G1,G2:env} {t1,t2:ty}
(pf: RT20 (t1, t2) | vm: VM (G1, G2)): VM (t1 :: G1, t2 :: G2) =
lam x1 => case+ x1 of
| VARone () => (pf | VARone)
| VARshi x1 => let val (pf | x2) = vm x1 in (pf | VARshi x2) end
fun cps {G1,G2:env} {t1,t2:ty}
(pf: RT10 (t1, t2) | vm: VM (G1, G2), e: EXP (G1, t1)): EXP' (G2, t2) =
let prval RT1 (pf) = pf in EXPlam' (cpsw (pf | vmShi vm, EXPone1 (), e)) end
and cpsw {G1,G2:env} {t1,t2:ty}
(pf: RT20 (t1, t2) | vm: VM (G1, G2), k: EXP' (G2, t2 ->> bot), e: EXP (G1, t1))
: EXP' (G2, bot) = begin case+ e of
| EXPvar x1 => let
val (pf' | x2) = vm x1
prval TYEQ () = rt2eq (pf, pf')
in
EXPapp' (k, EXPvar' x2)
end
| EXPlam e => let
prval RT2fun (pf1, pf2) = pf
in
EXPapp' (k, EXPlam' (cps (pf2 | vmLam (pf1 | vm), e)))
end
| EXPapp {..} {t, _} (e1, e2) => let
prval pf1 = rt2fun {t} ()
val k = EXPlam' (EXPapp' (EXPapp' (EXPtwo1 (), EXPone1 ()), expShi (expShi k)))
val k = EXPlam' (cpsw (pf1 | vmShi vm, k, e2))
in
cpsw (RT2fun (pf1, RT1 pf) | vm, k, e1)
end
| EXPlet {..} {t, _} (e1, e2) => let
prval pf1 = rt2fun {t} ()
val k = EXPlam' (
EXPlet' (EXPone1 (), expShi (cpsw (pf | vmLam (pf1 | vm), expShi k, e2)))
)
in
cpsw (pf1 | vm, k, e1)
end
| EXPcal e => let
val k = expShi k
val k = EXPlam' (EXPapp' (EXPapp' (EXPone1 (), k), k))
in
cpsw (RT2fun (RT2cont pf, RT1 pf) | vm, k, e)
end
| EXPthr {..} {t,_} (e1, e2) => let
prval pf1 = rt2fun {t} ()
val k = EXPlam' (cpsw (pf1 | vmShi vm, EXPone1 (), e2))
in
cpsw (RT2cont pf1 | vm, k, e1)
end
end
fn cps0 {t1,t2:ty} (pf: RT10 (t1, t2) | e: EXP0 t1): EXP0' t2 =
cps (pf | vmNil, e)
val ans1: [t:ty] EXP0' t = let
prval [t2:ty] pf = rt1fun {int ->> int} ()
in
cps0 {int->>int,t2} (pf | EXPlam {nil} {int,int} (EXPvar VARone))
end
implement main (argc, argv) = let
in
print "ans1 = "; print ans1; print_newline ();
end