Lectures onType Theory
Specialization, supercompilation, and staging
appendix sectionrules

Specialization, supercompilation, and staging

Scheme0 evaluation and specialization

Scheme0 expressions contain constants, variables, primitives, conditionals, and named first-order calls. Its complete call-by-value evaluator is

P;ρc[[c]]
S0-Const
ρ(x)=v
P;ρxv
S0-Var
P;ρevδ(op,v)=v
P;ρop(e)v
S0-Op
P;ρe0falseP;ρe2v
P;ρif e0 e1 e2v
S0-If-F
P;ρe0v0v0falseP;ρe1v
P;ρif e0 e1 e2v
S0-If-T
P;ρevP(f)=(x,ef)P;[xv]efv
P;ρcall f ev
S0-Call

Thus the second branch is selected exactly at false, and the first branch at every other value.

The online numeric projection returns either known(n) or res(r). Its complete nonrecursive card is

ρspenknown(n)
PE-Num
ρs(x)=n
ρspexknown(n)
PE-Static
xdom(ρs)
ρspexres(x)
PE-Dynamic

For {+,}, arithmetic uses

ρspee1known(n1)ρspee2known(n2)
ρspee1e2known(n1n2)
PE-Op-S
ρspee1q1ρspee2q2(r1. q1=res(r1))(r2. q2=res(r2))
ρspee1e2res(lift(q1)lift(q2))
PE-Op-D

The conditional rules are

ρspee0known(0)ρspee1q
ρspeif0 e0 then e1 else e2q
PE-If-Z
ρspee0known(n+1)ρspee2q
ρspeif0 e0 then e1 else e2q
PE-If-N
ρspee0res(r0)ρspee1q1ρspee2q2
ρspeif0 e0 then e1 else e2res(if0 r0 thenlift(q1) elselift(q2))
PE-If-D

The fuelled call judgment is b;μ;ρspeeq;μ. With P(f)=(xs;xd;ef), π=(f,n), and componentwise q^=lift(q), every noncall rule above lifts by threading the table through its premises from left to right while leaving the budget unchanged. Its three call rules are

b;μ;ρspeesknown(n);μ1b;μ1;ρspeedq;μ2name(μ2(π))=h
b;μ;ρspecall f(es;ed)res(call h(q^));μ2
PE-Call-Hit
0;μ;ρspeesknown(n);μ10;μ1;ρspeedq;μ2πdom(μ2)
0;μ;ρspecall f(es;ed)res(call f(n;q^));μ2
PE-Fuel
(b+1);μ;ρspeesknown(n);μ1(b+1);μ1;ρspeedq;μ2πdom(μ2)h freshμ3=μ2[πh]b;μ3;[xsn]peefqf;μ4μ5=complete(μ4,π,h(xd)=lift(qf))
(b+1);μ;ρspecall f(es;ed)res(call h(q^));μ5
PE-Call-New

The offline binding-time checker uses b{S,D} and a division τ from variables to binding times. Its exact rules are

τc:S
BT-Const
τ(x)=b
τx:b
BT-Var
τei:S(1ia)
τops(e1,,ea):S
BT-Op-S
τei:D(1ia)
τopd(e1,,ea):D
BT-Op-D
τe0:Sτe1:bτe2:b
τifs(e0,e1,e2):b
BT-If-S
τe0:Dτe1:Dτe2:D
τifd(e0,e1,e2):D
BT-If-D
τei:S(1ia)
τcallsf(e1,,ea)():S
BT-Call-S0

For m<a, calls with dynamic arguments use

τei:S (1im)τei:D (m<ia)
τcallsf(e1,,em)(em+1,,ea):D
BT-Call-S
τei:S (1im)τei:D (m<ia)
τcalldf(e1,,em)(em+1,,ea):D
BT-Call-D
τe:S
τlift(e):D
BT-Lift

For offline specialization, write q::=val(v)code(r) and ξ=(ρs;ηd). Its complete scalar rule card is

Pb;ξoffcval([[c]])
Off-Const
ρs(x)=v
Pb;ξoffxval(v)
Off-Var-S
ηd(x)=r
Pb;ξoffxcode(r)
Off-Var-D
Pb;ξoffeval(v)δ(op,v)=v
Pb;ξoffops(e)val(v)
Off-Op-S
Pb;ξoffecode(r)
Pb;ξoffopd(e)code(op(r))
Off-Op-D
Pb;ξoffe0val(v0)j=1 if v0false, j=2 otherwisePb;ξoffejq
Pb;ξoffifs(e0,e1,e2)q
Off-If-S
Pb;ξoffeicode(ri)(0i2)
Pb;ξoffifd(e0,e1,e2)code(if r0 r1 r2)
Off-If-D

If Pb(f)=(xs;xd;efb), calls and lifting use

Pb;ξoffesval(v)Pb;ξoffedcode(r)Pb;([xsv];[xdr])offefbq
Pb;ξoffcallsf(es)(ed)q
Off-Call-S
Pb;ξoffesval(v)Pb;ξoffedcode(r)
Pb;ξoffcalldf(es)(ed)code(call fv(r))
Off-Call-D
Pb;ξoffeval(v)
Pb;ξofflift(e)code(quote(v))
Off-Lift

The corresponding vector judgments apply these scalar rules from left to right. Offline residualization returns a program only through a finite completed graph (ν,E,r0): ν injectively names every reached static call state, E contains the specialized equation for each named state, every residual call targets another state in dom(ν), and the main expression yields r0. A state is named before its body is specialized, so a revisit is a back edge. If this reachability expansion does not terminate, no residual program is returned. The finite-return proof maintains Ik(μ,μ): every pending entry has one allocating ancestor and one eventual equation, every completed entry simulates its source body below height k, and fuel-zero retention is closed under source calls. Recursive hits are justified by smaller evaluation height, not by induction on the cyclic table.

SC-CBV driving, folding, and whistle

An SC-CBV configuration is a residual context focused on one expression. The source’s letrec is macro-expanded using its distinguished global fixpoint before concrete evaluation. The chapter’s pedagogical projection drive0 is partial and contains only beta, known-case, and open-case configurations; the full driver is the ordered source ledger R1–R20. Write Re for context plugging, let a range over obstructed expressions, and let ρ record fresh residual names paired with earlier calls. For B={piei}i, put BxR={piD[]((Rei)[pi/x])}i,BR={piD[](Rei)}i. The complete ordered ledger is R1R3:DR(n)=Rn,DR(x)=Rx,DR(g)=DRapp(g);R4R6:D[](k(e))=k(D[](e)),DR(xe)=RxD[](e),D[](λx.e)=λx.D[](e);R7:DR(n1n2)=D[](Rn),n=prim(n1,n2). R8:DR(e1e2)={D[](e1)D[](e2),e1e2=a,DRe1[](e2),e1=n or a,DR[]e2(e1),otherwise. R9R10:DR((λx.f)e)=DR(let x=e in f),DR(ee)=DR[]e(e);R11R12:DR(let x=n in f)=D[](Rf[n/x]),DR(let x=y in f)=D[](Rf[y/x]), where the last equation requires that y was not introduced by a preceding split. For R13, let L=let x=e in f and Q=xstrict(f)linear(f). Then R13:DR(L)={D[](Rf[e/x]),Q,let x=D[](e) inD[](Rf),otherwise;R14:DR(letrec g=v in e)=D[],G,ρ(Re),G=G{gv};R15R17:DR(C[x;B])=C[x;BxR],DR(C[kj(e);B])=D[](Rlet xj=e in ej),DR(C[nj;B])=D[](Rej);R18R20:DR(C[a;B])=C[D[](a);BR],DR(C[e;B])=DRcase(e),DR(e)=Re. Here Rcase=RC[[];B] in R19; the rules are tried in numerical order. The obstructed grammar is a::=xnaanaaae.

The application ledger completes the driver card. An entry for a configuration Q, with ordered free-variable vector x, is ρ(h)=λx.Q; write (h,Q)ρ for this assertion. Put g^=Rg. The alternatives are tried in the displayed order: A1:DR,G,ρapp(g)=hx,(h,e1)ρ,σe1=g^,x=σ(fv(e1));A2:DR,G,ρapp(g)=g^,(h,e1)ρ,e1g^e1;A3:DR,G,ρapp(g)=[D[](f)/y]D[](fg),(h,e1)ρ,e1g^,(fg,f,y)=split(g^,e1). If none of A1–A3 applies, choose the first residual name h allowed by the chapter’s allocation condition and put (g,v)G,x=fv(g^),ρ=ρ{hλx.g^},e=D[],G,ρ(Rv). For Sub(e), the finite set of strict proper subexpressions of e, the remaining ordered alternatives are A4a:DR,G,ρapp(g)=[D[](f)/y]D[](fg),e1Sub(e) is the selected term,e1g^,g^e1,(fg,f,y)=split(g^,e1);A4b:DR,G,ρapp(g)=letrec h=λx.e in hx,hfn(e);A4c:DR,G,ρapp(g)=e,hfn(e).

The pedagogical projection’s beta rule is

drive0(R(λx.e)v)={([v/x],Re)}
D-Beta

For B={ci(xi)ei}iI, put θj=[cj(zj)/y],Qj=Rθjcase cj(zj) of B. A known constructor case selects one branch and substitutes its fields; an open-variable case refines the scrutinee once for every constructor and retains the case for the next known-case node:

jI
drive0(Rcase cj(v) of B)={([v/xj],Rej)}
D-Case-Known
y is freejI
drive0(Rcase y of B)={(θj,Qj)}jI
D-Case-Open

For beta and known-case edges, compatibility means the closed parent takes one concrete call-by-value contraction to the instantiated child; for an open-case edge it means equality after shape refinement. Alpha-equivalent configurations fold to the earlier residual function. Homeomorphic embedding on constructor trees is generated by

xy
Emb-Var
n1n2
Emb-Num
sti
sc(t1,,tk)
Emb-Dive
siti(1ik)
c(s1,,sk)c(t1,,tk)
Emb-Couple

When the whistle fires, most-specific generalization returns substitutions (θ1,θ2) and a common pattern g with gθ1=e1 and gθ2=e2; processing continues on the smaller generalized nodes under the source’s memo invariant.

The dual-context staging core

Tstage separates persistent assumptions u::AΔ from ordinary assumptions x:AΓ:

x:AΓ
Δ;Γx:A
T-Var
u::AΔ
Δ;Γu:A
T-MVar
Δ;Γ,x:AM:B
Δ;Γλx:A.M:AB
T-Abs
Δ;ΓM:ABΔ;ΓN:A
Δ;ΓMN:B
T-App
Δ;M:A
Δ;Γbox M:A
T-Box
Δ;ΓM:AΔ,u::A;ΓN:B
Δ;Γlet box u=M in N:B
T-LetBox

Staged computation has the two contractions

(λx:A.M)NM[N/x]
TS-Beta
let box u=box M in NN[M/u]
TS-BoxBeta

Its complete compatible closure is

MM
λx:A.Mλx:A.M
TS-Lam
MM
MNMN
TS-AppL
NN
MNMN
TS-AppR
MM
let box u=M in Nlet box u=M in N
TS-LetL
NN
let box u=M in Nlet box u=M in N
TS-LetR

There is no congruence beneath a box. The box-introduction premise’s empty ordinary context is the scope invariant; persistent substitution may cross a box and ordinary substitution may not.

Davies–Pfenning’s conservative two-level source is a different card. It has run-time and compile-time judgments Δ;Γre:τ and Δce:σ, with separately phase-marked Mini-ML constructors for functions, products, unit, naturals, case, and fixed points. For p{r,c}, let Cr=Δ;Γ and Cc=Δ. Its ordinary constructors have the complete phase-indexed rule schema

x:TCp
Cppx:T
2-Varp
Cp,x:T1pe:T2
Cppλpx:T1.e:T1T2
2-Lamp
Cppe1:T1T2Cppe2:T1
Cppe1@pe2:T2
2-Appp
Cp,x:Tpe:T
Cppfixpx:T.e:T
2-Fixp
Cppe1:T1Cppe2:T2
Cppe1,e2p:T1×T2
2-Pairp
Cppe:T1×T2
Cppprojip(e):Ti
2-Projp
Cppp:1
2-Unitp
Cppzp:nat
2-Zerop
Cppe:nat
Cppspe:nat
2-Succp
Cppe0:natCppez:TCp,x:natpes:T
Cppcasep e0 of zezsxes:T
2-Casep

Its only phase-changing rules are

Δce:τ
Δ;Γre:τ
2-Down
Δ;re:τ
Δce:τ
2-Up

The mutually recursive translation sends τ to τ and has the exact boundary equations e=unbox1|e|,|e|=boxe. The target judgment SiM:A uses a stack of ordinary contexts. Its load-bearing function and boundary rules are

x:Tlast(S)
Six:T
I-Var
S,x:TiM:U
Siλx:T.M:TU
I-Abs
SiM:TUSiN:T
SiMN:U
I-App
S;iM:T
SiboxM:T
I-Box
SiM:T
S;Γiunbox1M:T
I-Unbox1

The remaining target rules are

S,x:TiM:T
Sifix x:T.M:T
I-Fix
SiM:T1SiN:T2
SiM,N:T1×T2
I-Pair
SiM:T1×T2
Siprojj(M):Tj
I-Proj
Si:1
I-Unit
Siz:nat
I-Zero
SiM:nat
SisM:nat
I-Succ
SiM:natSiMz:TS,x:natiMs:T
Sicase M of zMzsxMs:T
I-Case

Box pushes an empty component and unbox1 crosses exactly one boundary. These are every target family used by the translation. Its conservative embedding proves both preservation and reflection of the two typing judgments; it is not a relabelling of Tstage.

MacoCaml compilation boundary

The separate MacoCaml source judgment σ1;Ω;Γne:τe;σ2,{c,s,q}, threads a compile-time heap, records the integer binding level and compiler mode, and returns elaborated core syntax. Quotation and nested splice are

σ1;Ω;Γn+1qe:τe;σ2
σ1;Ω;Γncse:Codeτe;σ2
MC-Quote
σ1;Ω;Γn1se:Codeτe;σ2
σ1;Ω;Γnq$e:τ$e;σ2
MC-Splice

The symbol cs denotes one rule instance at each mode. A top-level splice instead uses

σ1;Ω;Γn1se:Codeτe;σ2σ2;Ωe0v;σ3
σ1;Ω;Γnc$e:τv;σ3
MC-CodeGen

The empty-heap consequence is theorem 129.10. These rules are not modal box rules.

Tan–Wei semantics-preserving two-stage cards

The pure comparison calculus λ|2| has stages s{1,2}, reification effects ϵ{,}, and the two judgments Γst:τϵ,Γt:τϵ. Its code types distinguish complete code rep(τ) from a reifiable fragment frag(τ). The bridge rules are

Γ1t:τ
Γt:τ
TW-Pure
Γ1t:frag(τ)ϵ
Γt:rep(τ)ϵ
TW-Rep

The administrative rules are

Γ2t:τ
Γ1code t:rep(τ)
TW-Code
Γ2t:τ
Γ1reflect t:frag(τ)
TW-Reflect
Γ2t1:τ1Γ,x2:τ1t2:rep(τ2)ϵWF2(τ1)
Γ1letc x=t1 in t2:rep(τ2)
TW-LetC

For x fresh, automatic let insertion is the root-compatible step P[E[reflect t]]P[letc x=t in E[code x]], where E contains only ordinary pure evaluation frames and P is a reification context. Stage erasure sends inserted letc to ordinary let and deletes the remaining administrative staging forms.

The λ|2|ref delta adds natural-number locations and stores. Generated-stage allocation, get, and put build fragments under 1; the corresponding executing operations occur only under 2. The run-rule delta is

storeFree(t)t:rep(τ)ϵ
Γ1run t:τ
TW-Run-Ref

Its store-freedom and empty-context premises ensure that first-stage evaluation begins and ends with the empty store. Its logical relation adds a world which is a partial bijection of locations and extends that world after allocation. The exact pure and reference consequences are lemma 129.11, theorem 129.12; neither card is Tstage, MetaOCaml, or LMS.

Dependent multistage typing

Stages are finite words A,B over stage variables. Context declarations record an exact stage, and variable use requires that exact match. Kinds and types have the complete formation and checking rules

Γ kind@A
MD-Kind-Star
Γτ::@AΓ,x:τ@AK kind@A
ΓΠx:τ.K kind@A
MD-Kind-Pi
X::KΣ
ΓX::K@A
MD-TConst
Γσ::Πx:τ.K@AΓM:τ@A
ΓσM::K[M/x]@A
MD-TApp
Γτ::@Aα
Γατ::@A
MD-TCode
Γτ::K@AαFTV(Γ)FTV(A)
Γα.τ::K@A
MD-TForall
Γτ::@A
Γτ::@Aα
MD-TCSP
Γτ::K@AΓKJ@A
Γτ::J@A
MD-TConv
Γτ::@AΓ,x:τ@Aσ::@A
ΓΠx:τ.σ::@A
MD-Pi

The complete term-typing card begins with

c:τΣ
Γc:τ@A
MD-Const
x:τ@AΓ
Γx:τ@A
MD-Var
Γτ::@AΓ,x:τ@AM:σ@A
Γλx:τ.M:Πx:τ.σ@A
MD-Abs
ΓM:Πx:τ.σ@AΓN:τ@A
ΓMN:σ[N/x]@A
MD-App
ΓM:τ@AΓτσ::@A
ΓM:σ@A
MD-Conv

Quotation, escape, stage abstraction/application, and cross-stage persistence are

ΓM:τ@Aα
ΓMα:ατ@A
MD-Quote
ΓM:ατ@A
ΓαM:τ@Aα
MD-Escape
ΓM:τ@AαFTV(Γ)FTV(A)
ΓΛα.M:α.τ@A
MD-SAbs
ΓM:α.τ@A
ΓMB:τ[B/α]@A
MD-SApp
ΓM:τ@A
Γ%αM:τ@Aα
MD-CSP

The three equality judgments are ΓKJ@A, Γτσ::K@A, and ΓMN:τ@A. Kind equality is generated by

Γτσ::@AΓ,x:τ@AKJ@A
ΓΠx:τ.KΠx:σ.J@A
MD-QK-Pi
ΓKJ@A
ΓKJ@Aα
MD-QK-CSP
ΓK kind@A
ΓKK@A
MD-QK-Refl
ΓKJ@A
ΓJK@A
MD-QK-Sym
ΓKJ@AΓJI@A
ΓKI@A
MD-QK-Trans

Type equality is generated by

Γτσ::@AΓ,x:τ@Aρπ::@A
ΓΠx:τ.ρΠx:σ.π::@A
MD-QT-Pi
Γτσ::Πx:ρ.K@AΓMN:ρ@A
ΓτMσN::K[M/x]@A
MD-QT-App
Γτσ::@Aα
Γατασ::@A
MD-QT-Code
Γτσ::@AαFTV(Γ)FTV(A)
Γα.τα.σ::@A
MD-QT-Forall
Γτσ::@A
Γτσ::@Aα
MD-QT-CSP
Γτ::K@A
Γττ::K@A
MD-QT-Refl
Γτσ::K@A
Γστ::K@A
MD-QT-Sym
Γτσ::K@AΓσρ::K@A
Γτρ::K@A
MD-QT-Trans

Term congruence and equivalence are

Γτσ::@AΓ,x:τ@AMN:ρ@A
Γλx:τ.Mλx:σ.N:Πx:τ.ρ@A
MD-Q-Abs
ΓML:Πx:σ.τ@AΓNO:σ@A
ΓMNLO:τ[N/x]@A
MD-Q-App
ΓMN:τ@Aα
ΓMαNα:ατ@A
MD-Q-Quote
ΓMN:ατ@A
ΓαMαN:τ@Aα
MD-Q-Escape
ΓMN:τ@AαFTV(Γ)FTV(A)
ΓΛα.MΛα.N:α.τ@A
MD-Q-SAbs
ΓMN:α.τ@A
ΓMBNB:τ[B/α]@A
MD-Q-SApp
ΓMN:τ@A
Γ%αM%αN:τ@Aα
MD-Q-CSP
ΓM:τ@A
ΓMM:τ@A
MD-Q-Refl
ΓMN:τ@A
ΓNM:τ@A
MD-Q-Sym
ΓMN:τ@AΓNL:τ@A
ΓML:τ@A
MD-Q-Trans

Its four computational axioms are

Γ,x:σ@AM:τ@AΓN:σ@A
Γ(λx:σ.M)NM[N/x]:τ[N/x]@A
MD-Q-Beta
ΓMN:τ@Aα
ΓαMαN:τ@Aα
MD-Q-Splice
ΓΛα.M:α.τ@A
Γ(Λα.M)BM[B/α]:τ[B/α]@A
MD-Q-StageBeta
ΓM:τ@AαΓM:τ@A
Γ%αMM:τ@Aα
MD-Q-Percent

For staged evaluation, constant-headed neutral spines and values are defined mutually by hε::=chεvεhεB,hA::=cxhAvAhABαhε(A=α),vε::=hελx:τ.MvααΛα.vε,vA::=hAλx:τ.vAvAvAvAααΛα.vAvABαvA(A=Aα, Aε)%αvA(A=Aα). Let D be either ε or one stage variable. The hole of EDA lies at stage D, and the whole context lies at stage A: EDε::=[] (D=ε)EDεMvεEDεEDααΛα.EDεEDεC,EDA::=[] (A=D)λx:τ.EDAEDAMvAEDAEDAαααEDA (Aα=A)Λα.EDAEDAC%αEDA (Aα=A). The redex grammar is Rε::=(λx:τ.M)vε(Λα.vε)C,Rα::=αvαα. The staged relation consists exactly of EεA[(λx:τ.M)vε]sEεA[M[vε/x]],EεA[(Λα.vε)C]sEεA[vε[C/α]],EαA[αvαα]sEαA[vα]. These are published λMD rules. The theorem-bearing book-local system λisMD deletes type-equivalence rule MD-QT-CSP; code-head inversion additionally states the body-formation premise required because the remaining type-level CSP formation rule can move a code type to a later word. Its staged final forms extend the published value grammar by constant-headed spines, which repairs stuck function-constant applications without adding a full-reduction rule. Its full contexts remain in the term syntactic category and never enter a binder annotation, type, or kind. A typed dependent-annotation peak therefore refutes exact syntactic confluence; the chapter proves confluence only modulo binder-annotation erasure. These explicit boundaries govern the chapter’s preservation, term-only normalization, annotation-erased confluence, decomposition, and staged-progress proofs. They are not the exact published metatheorem package.

Search the book

Type to search the local edition.