Typed Multi-Stage Programming and an Evidence-Bounded Interpreter-Tower Case Study
Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
The untyped generator 𝗉𝗈𝗐(1,𝑥)=𝑥 and 𝗉𝗈𝗐(𝑛+1,𝑥)=𝑥⋅𝗉𝗈𝗐(𝑛,𝑥) should turn a known exponent three into future code 𝑥⋅(𝑥⋅𝑥). If quotation captures a generation-time variable, however, the alleged program may contain a free name after the generator returns. Staging needs a typing judgment that records which assumptions survive quotation.
The modal box closes future code
Fix simple types 𝐴,𝐵::=𝑏∣𝐴→𝐵∣◻𝐴 and terms 𝑀,𝑁::=𝑥∣𝜆𝑥:𝐴.𝑀∣𝑀𝑁∣𝖻𝗈𝗑𝑀∣𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝑁. The judgment Δ;Γ⊢𝑀:𝐴 separates modal assumptions 𝑢::𝐴∈Δ, available under boxes, from ordinary assumptions 𝑥:𝐴∈Γ, available only at the present stage.
𝑥:𝐴∈Γ
Δ;Γ⊢𝑥:𝐴
T-Var
𝑢::𝐴∈Δ
Δ;Γ⊢𝑢:𝐴
T-MVar
Δ;Γ,𝑥:𝐴⊢𝑀:𝐵
Δ;Γ⊢𝜆𝑥:𝐴.𝑀:𝐴→𝐵
T-Abs
Δ;Γ⊢𝑀:𝐴→𝐵Δ;Γ⊢𝑁:𝐴
Δ;Γ⊢𝑀𝑁:𝐵
T-App
Δ;∅⊢𝑀:𝐴
Δ;Γ⊢𝖻𝗈𝗑𝑀:◻𝐴
T-Box
Δ;Γ⊢𝑀:◻𝐴Δ,𝑢::𝐴;Γ⊢𝑁:𝐵
Δ;Γ⊢𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝑁:𝐵
T-LetBox
This is the pure dual-context modal-S4 calculus 𝖳𝗌𝗍𝖺𝗀𝖾. Rule T-Box empties the ordinary context. It accepts 𝑢::𝑏;∅⊢𝖻𝗈𝗑𝑢:◻𝑏, but rejects ∅;𝑥:𝑏⊢𝖻𝗈𝗑𝑥:◻𝑏. The rejection is the scope-extrusion counterexample, not a missing coercion.
Code values are 𝖻𝗈𝗑𝑀. Staged reduction has two contractions and five congruence families:
(𝜆𝑥:𝐴.𝑀)𝑁⟶𝑀[𝑁/𝑥]
TS-Beta
𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝖻𝗈𝗑𝑀𝗂𝗇𝑁⟶𝑁[𝑀/𝑢]
TS-BoxBeta
𝑀⟶𝑀′
𝜆𝑥:𝐴.𝑀⟶𝜆𝑥:𝐴.𝑀′
TS-Lam
𝑀⟶𝑀′
𝑀𝑁⟶𝑀′𝑁
TS-AppL
𝑁⟶𝑁′
𝑀𝑁⟶𝑀𝑁′
TS-AppR
𝑀⟶𝑀′
𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝑁⟶𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀′𝗂𝗇𝑁
TS-LetL
𝑁⟶𝑁′
𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝑁⟶𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝑁′
TS-LetR
There is no congruence beneath 𝖻𝗈𝗑: its body is future syntax.
The modal eta expansion is 𝑀:◻𝐴↦𝗅𝖾𝗍𝖻𝗈𝗑𝑢=𝑀𝗂𝗇𝖻𝗈𝗑𝑢, with 𝑢 fresh. Its typing derivation first applies T-LetBox; in the body, T-MVar derives 𝑢:𝐴 and T-Box closes the empty ordinary context. Thus eta expresses local completeness of elimination followed by introduction. It is an expansion principle, not a staged evaluation step.
If multiplication is a modal constant 𝑚::𝑏→𝑏→𝑏, repeated T-LetBox constructs 𝑢::𝑏;∅⊢𝖻𝗈𝗑(𝑚𝑢(𝑚𝑢𝑢)):◻𝑏. Each occurrence of 𝑢 is modal. Replacing it by an ordinary 𝑥:𝑏 invalidates the premise of T-Box.
Proof. For ordinary substitution, induct on the derivation of 𝑀. The variable case uses the second premise when its variable is 𝑥. Under T-Box, the premise has empty ordinary context, so 𝑥 cannot occur; weakening the unchanged premise concludes the case. Abstraction and application use their induction hypotheses. In T-LetBox, apply them to both premises after alpha-renaming the modal binder away from 𝑁.
For modal substitution, use the same induction. Rule T-MVar uses the closed ordinary-context premise when its variable is 𝑢. Rule T-Box admits that premise because modal assumptions remain available under a box. The binder case is handled by alpha-renaming. These are all six rule families. ◻
Call a subterm occurrence persistent when it lies beneath a box; other occurrences are eliminable. A term is irreducible when none of the seven staged rules applies. In the labelled syntax, labels are inert metadata: a contraction transports labels on retained syntax and on every copied substitution instance, and no operational rule creates or erases a label.
If ∅;∅⊢𝑀:◻𝐴, 𝑀⟶∗𝑀′, and 𝑀′ is irreducible, then every occurrence of the body 𝑁, viewed as an occurrence in 𝑀′=𝖻𝗈𝗑𝑁, is persistent; the root occurrence 𝖻𝗈𝗑𝑁 is not asserted to lie beneath itself. Moreover, extend terms by inert labels 𝑀ℓ, label every persistent occurrence of a well-typed 𝑀, and suppose 𝑀⟶𝑀′. Every persistent occurrence of 𝑀′ still carries ℓ.
Proof of Theorem 129.2 — Local eliminability and inert-label persistence
Proof. Induction on the finite reduction sequence, using the two substitution clauses at the two contractions, gives ∅;∅⊢𝑀′:◻𝐴. A simultaneous induction on a closed irreducible typing derivation gives the needed canonical-form fact. The variable case is impossible. An abstraction has arrow type. In an application, the induction hypothesis makes a closed irreducible function of arrow type an abstraction, so beta would apply. In a let-box term, the induction hypothesis makes its irreducible scrutinee a box, so let-box beta would apply. Therefore a closed irreducible term of type ◻𝐴 is 𝖻𝗈𝗑𝑁. Every occurrence belonging to its body 𝑁 lies below that box.
For persistence, induct on the staged reduction. In ordinary beta, the modal typing restriction prevents the substituted ordinary variable from occurring beneath a box; this follows by induction on the body typing derivation. In let-box beta, every occurrence of the substituted code body was labelled in the boxed premise. Congruence preserves labels by the induction hypothesis. There is no box congruence, so no reduction changes a labelled occurrence already beneath a box. These are the two contractions and five congruence families; labels add no reduction rule. This is a theorem of the displayed unlabelled dual-context calculus extended with inert occurrence metadata. Davies and Pfenning’s source calculus also has labelled expressions 𝐸ℓ, an explicit unlabelling contraction, and labelled case analysis. Its Theorems 5–6 prove eliminability and persistence for that richer operational system [DP01]; the local theorem neither imports nor silently omits those additional rules. ◻
If Δ;Γ⊢𝑀:𝐴 and 𝑀⟶𝑀′, then Δ;Γ⊢𝑀′:𝐴. Hence a closed term of type ◻𝐴 that evaluates to 𝖻𝗈𝗑𝑁 has ∅;∅⊢𝑁:𝐴; generated code has no escaped ordinary variable.
Proof of Theorem 129.3 — Subject reduction and scope safety
Proof. Induct on the reduction derivation. Beta uses ordinary substitution. Let-box beta uses modal substitution. Compatible cases rebuild their typing rule with the induction hypothesis. If a closed term evaluates to a code value, preservation gives ∅;∅⊢𝖻𝗈𝗑𝑁:◻𝐴; inversion of T-Box gives the conclusion. ◻
★☆☆ The term 𝜆𝑥:𝑏.𝖻𝗈𝗑𝑥 fails to type. Repair it by taking a boxed argument and using T-LetBox. Give the complete derivation and the two-step reduction sequence on argument 𝖻𝗈𝗑𝑐, identifying the TS-BoxBeta step.
MetaML-style quotation and escape use stage-indexed contexts and may include cross-stage persistence. A sound CSP rule must restrict the persisted values; persisting a mutable reference would let future code retain a cell from a completed run. 𝖳𝗌𝗍𝖺𝗀𝖾 has no CSP rule, reference, or run operator, so theorem 129.3 says nothing about that extension. For comparison only, fix the pure two-stage MetaML fragment with 𝜏::=𝑏∣𝜏→𝜏∣𝖢𝗈𝖽𝖾𝛼𝜏, stage words 𝐴, and judgments Γ⊢𝐴𝑀:𝜏. Its deliberately restrictive persistent-value predicate is generated by
𝑐𝑏isaclosedimmutableliteral
𝖯𝖾𝗋𝗌(𝑐𝑏:𝑏)
Pers-Base
∅⊢𝐴⟨𝑀⟩𝛽:𝖢𝗈𝖽𝖾𝛽𝜏Loc(𝑀)=∅
𝖯𝖾𝗋𝗌(⟨𝑀⟩𝛽:𝖢𝗈𝖽𝖾𝛽𝜏)
Pers-Code
Here Loc(𝑀) is the finite set of store locations occurring in 𝑀; it is empty throughout the pure fragment. There is no persistent function clause. The three-rule delta is
Γ⊢𝐴𝛼𝑀:𝜏
Γ⊢𝐴⟨𝑀⟩𝛼:𝖢𝗈𝖽𝖾𝛼𝜏
MML-Quote
Γ⊢𝐴𝑀:𝖢𝗈𝖽𝖾𝛼𝜏
Γ⊢𝐴𝛼∼𝛼𝑀:𝜏
MML-Escape
Γ⊢𝐴𝑣:𝜏𝖯𝖾𝗋𝗌(𝑣:𝜏)
Γ⊢𝐴𝛼%𝛼𝑣:𝜏
MML-CSP
The side condition is load-bearing. If it admitted locations, then 𝗅𝖾𝗍𝑟=𝗋𝖾𝖿0𝗂𝗇⟨𝗀𝖾𝗍(%𝛼𝑟)⟩𝛼 would return code containing 𝑟 after the allocating run ended. The two constructors of 𝖯𝖾𝗋𝗌 reject that location. This card states no store theorem; it exposes one exact safe fragment and the smallest premise that a reference-bearing extension would have to replace with a world-indexed store invariant.
The source comparison is not a renaming of 𝖳𝗌𝗍𝖺𝗀𝖾. Davies and Pfenning’s two-level Mini-ML has run-time types 𝜏::=𝗇𝖺𝗍∣𝜏→𝜏∣𝜏×𝜏∣1 and compile-time types 𝜎::=𝗇𝖺𝗍∣𝜎→𝜎∣𝜎×𝜎∣1∣𝜏――. Terms have separately underlined run-time and overlined compile-time constructors for variables, abstraction, application, fixed points, pairs, projections, unit, zero, successor, and natural-number case. The two judgments are Δ;Γ⊢𝑟𝑒:𝜏 and Δ⊢𝑐𝑒:𝜎. For 𝑝∈{𝑟,𝑐}, every constructor has the following phase-indexed schema (with C𝑟=Δ;Γ, C𝑐=Δ, and a binder added to the corresponding context):
𝑥:𝑇∈C𝑝
C𝑝⊢𝑝𝑥:𝑇
2-Varp
C𝑝,𝑥:𝑇1⊢𝑝𝑒:𝑇2
C𝑝⊢𝑝𝜆𝑝𝑥:𝑇1.𝑒:𝑇1→𝑇2
2-Lamp
C𝑝⊢𝑝𝑒1:𝑇1→𝑇2C𝑝⊢𝑝𝑒2:𝑇1
C𝑝⊢𝑝𝑒1@𝑝𝑒2:𝑇2
2-Appp
C𝑝,𝑥:𝑇⊢𝑝𝑒:𝑇
C𝑝⊢𝑝𝖿𝗂𝗑𝑝𝑥:𝑇.𝑒:𝑇
2-Fixp
C𝑝⊢𝑝𝑒1:𝑇1C𝑝⊢𝑝𝑒2:𝑇2
C𝑝⊢𝑝⟨𝑒1,𝑒2⟩𝑝:𝑇1×𝑇2
2-Pairp
C𝑝⊢𝑝𝑒:𝑇1×𝑇2
C𝑝⊢𝑝𝗉𝗋𝗈𝗃𝑝𝑖(𝑒):𝑇𝑖
2-Projp
C𝑝⊢𝑝⟨⟩𝑝:1
2-Unitp
C𝑝⊢𝑝𝗓𝑝:𝗇𝖺𝗍
2-Zerop
C𝑝⊢𝑝𝑒:𝗇𝖺𝗍
C𝑝⊢𝑝𝗌𝑝𝑒:𝗇𝖺𝗍
2-Succp
C𝑝⊢𝑝𝑒0:𝗇𝖺𝗍C𝑝⊢𝑝𝑒𝑧:𝑇C𝑝,𝑥:𝗇𝖺𝗍⊢𝑝𝑒𝑠:𝑇
C𝑝⊢𝑝𝖼𝖺𝗌𝖾𝑝𝑒0𝗈𝖿𝗓⇒𝑒𝑧∣𝗌𝑥⇒𝑒𝑠:𝑇
2-Casep
The two phase-transition rules are the entire rule delta:
Δ⊢𝑐𝑒:𝜏――
Δ;Γ⊢𝑟𝑒:𝜏
2-Down
Δ;∅⊢𝑟𝑒:𝜏
Δ⊢𝑐𝑒:𝜏――
2-Up
The mutually recursive translation ‖−‖ on run-time syntax and |−| on compile-time syntax is homomorphic on each phase’s constructors, maps |𝜏――| to ◻‖𝜏‖, and has the decisive equations ‖――𝑒‖=𝗎𝗇𝖻𝗈𝗑1|――𝑒|,|𝑒――|=𝖻𝗈𝗑‖𝑒――‖. Here the target is the source’s implicit multi-world Mini-ML, whose 𝗎𝗇𝖻𝗈𝗑1 discharges one context-stack boundary. Write S⊢𝑖𝑀:𝐴 for that target judgment: S is the stack of ordinary contexts, variables are selected from its active component, 𝖻𝗈𝗑 pushes an empty component, and 𝗎𝗇𝖻𝗈𝗑1 pops one component. Write S,𝑥:𝑇 for extension of its active component. The function and modal rules are
𝑥:𝑇∈last(S)
S⊢𝑖𝑥:𝑇
I-Var
S,𝑥:𝑇⊢𝑖𝑀:𝑈
S⊢𝑖𝜆𝑥:𝑇.𝑀:𝑇→𝑈
I-Abs
S⊢𝑖𝑀:𝑇→𝑈S⊢𝑖𝑁:𝑇
S⊢𝑖𝑀𝑁:𝑈
I-App
For every ordinary context Γ, the two boundary rules are
S;∅⊢𝑖𝑀:𝑇
S⊢𝑖𝖻𝗈𝗑𝑀:◻𝑇
I-Box
S⊢𝑖𝑀:◻𝑇
S;Γ⊢𝑖𝗎𝗇𝖻𝗈𝗑1𝑀:𝑇
I-Unbox1
Thus I-Box enters one future world and I-Unbox1 uses code from its immediate predecessor; the latter is not an unindexed run operation. The remaining constructor schemas are
S,𝑥:𝑇⊢𝑖𝑀:𝑇
S⊢𝑖𝖿𝗂𝗑𝑥:𝑇.𝑀:𝑇
I-Fix
S⊢𝑖𝑀:𝑇1S⊢𝑖𝑁:𝑇2
S⊢𝑖⟨𝑀,𝑁⟩:𝑇1×𝑇2
I-Pair
S⊢𝑖𝑀:𝑇1×𝑇2
S⊢𝑖𝗉𝗋𝗈𝗃𝑗(𝑀):𝑇𝑗
I-Proj
S⊢𝑖⟨⟩:1
I-Unit
S⊢𝑖𝗓:𝗇𝖺𝗍
I-Zero
S⊢𝑖𝑀:𝗇𝖺𝗍
S⊢𝑖𝗌𝑀:𝗇𝖺𝗍
I-Succ
S⊢𝑖𝑀:𝗇𝖺𝗍S⊢𝑖𝑀𝑧:𝑇S,𝑥:𝗇𝖺𝗍⊢𝑖𝑀𝑠:𝑇
S⊢𝑖𝖼𝖺𝗌𝖾𝑀𝗈𝖿𝗓⇒𝑀𝑧∣𝗌𝑥⇒𝑀𝑠:𝑇
I-Case
These displayed schemas are every target family used by the translation. This is the exact JACM card on printed pages 35–40; the term translation is on printed page 39 and the embedding theorem is on printed page 40. It is not the dual-context calculus above.
Both directions hold simultaneously: Δ;Γ⊢𝑟𝑒:𝜏⟺|Δ|;‖Γ‖⊢𝑖‖𝑒‖:‖𝜏‖,Δ⊢𝑐𝑒:𝜎⟺|Δ|⊢𝑖|𝑒|:|𝜎|. On each reverse implication, the target type is in the image of the displayed type translation. This theorem concerns typing; the two-level source has no direct reduction semantics in the selected presentation.
Proof. This is an exact import of Davies–Pfenning Theorem 15 [DP01]. The forward and reflection directions are proved simultaneously by structural induction on the two translations. Every homomorphic constructor uses the corresponding source and target rule plus its induction hypotheses. The only nonhomomorphic cases are 2-Down and 2-Up: the former translates to 𝗎𝗇𝖻𝗈𝗑1, and target inversion recovers the compile-time premise; the latter translates to 𝖻𝗈𝗑, and target inversion recovers the empty run-time context. Those inversions also prove that a target type in the translation image reflects to the unique source phase type. These cases and the homomorphic schema cover every printed rule family. ◻
For a self-contained arithmetic comparison, fix annotated terms 𝑎::=𝑛𝑆∣𝑥𝑆𝑠∣𝑥𝐷𝑑∣𝑎1+𝑏𝑎2∣𝑎1⋅𝑏𝑎2,𝑏∈{𝑆,𝐷}. An 𝑆-operation requires two 𝑆-operands. A 𝐷-operation accepts either binding time and embeds a computed numeral as a residual numeral. The formation judgment 𝑠⊢𝐴𝑎:𝑏, where 𝑠 is defined on every static variable, has rules
𝑠⊢𝐴𝑛𝑆:𝑆
A-Nat
𝑥𝑠∈dom(𝑠)
𝑠⊢𝐴𝑥𝑆𝑠:𝑆
A-SVar
𝑠⊢𝐴𝑥𝐷𝑑:𝐷
A-DVar
𝑠⊢𝐴𝑎1:𝑆𝑠⊢𝐴𝑎2:𝑆
𝑠⊢𝐴𝑎1⊙𝑆𝑎2:𝑆
A-Op-S
𝑠⊢𝐴𝑎1:𝑏1𝑠⊢𝐴𝑎2:𝑏2
𝑠⊢𝐴𝑎1⊙𝐷𝑎2:𝐷
A-Op-D
Define 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴 by recursion on a derivation of that judgment: 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑛𝑆,𝑠)=𝗏𝖺𝗅(𝑛),𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑥𝑆𝑠,𝑠)=𝗏𝖺𝗅(𝑠(𝑥𝑠)),𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑥𝐷𝑑,𝑠)=𝖼𝗈𝖽𝖾(𝑥𝑑),𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎1⊙𝑆𝑎2,𝑠)=𝗏𝖺𝗅(𝑛1⊙𝑛2),𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎1⊙𝐷𝑎2,𝑠)=𝖼𝗈𝖽𝖾(⌊𝑞1⌋⊙⌊𝑞2⌋), where ⊙∈{+,⋅}, 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎𝑖,𝑠)=𝗏𝖺𝗅(𝑛𝑖) in the static equation, 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎𝑖,𝑠)=𝑞𝑖 in the dynamic equation, ⌊𝗏𝖺𝗅(𝑛)⌋=𝑛, and ⌊𝖼𝗈𝖽𝖾(𝑟)⌋=𝑟. Its annotation erasure |𝑎|𝐴 removes superscripts. This grammar is the nonrecursive, conditional-free arithmetic sublanguage of the Scheme0 source card definition 127.1: 𝑥𝑆𝑠 marks a variable in the static environment, 𝑥𝐷𝑑 marks a residual variable, and the superscript on an operator is its binding-time annotation. No Scheme0 call, conditional, memo-table operation, or annotation inference is translated here.
For a residual arithmetic term 𝑟, define its Tstage body ⌜𝑟⌝𝐴 by mapping a numeral 𝑛 to a modal numeral constant ¯𝑛::𝑏, a residual variable 𝑥𝑑 to the modal variable 𝑥𝑑::𝑏, and 𝑟1⊙𝑟2 to ¯⊙⌜𝑟1⌝𝐴⌜𝑟2⌝𝐴, where ¯⊙::𝑏→𝑏→𝑏 is modal. For a specialization result 𝑞, let Δ𝑑(𝑎,𝑞) contain ¯𝑛::𝑏 for every numeral 𝑛 occurring in ⌊𝑞⌋, ¯⊙::𝑏→𝑏→𝑏 for every operator occurring in ⌊𝑞⌋, and 𝑥𝑑::𝑏 for every dynamic variable of 𝑎. This context is finite because 𝑎 and 𝑞 are finite syntax. Put 𝖼𝗈𝖽𝖾𝐴(𝑟):=𝖻𝗈𝗑⌜𝑟⌝𝐴 and use the meta-level observation 𝖾𝗑𝖾𝖼𝐴(𝖼𝗈𝖽𝖾𝐴(𝑟),𝑑)=𝑛⟺𝖾𝗏𝖺𝗅𝐴(𝑟,𝑑)=𝑛. Neither 𝖾𝗑𝖾𝖼𝐴 nor 𝖾𝗏𝖺𝗅𝐴 is a reduction rule of 𝖳𝗌𝗍𝖺𝗀𝖾.
Suppose 𝑠⊢𝐴𝑎:𝑏𝐴 and 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎,𝑠)=𝑞, where 𝑏𝐴∈{𝑆,𝐷}. Then Δ𝑑(𝑎,𝑞);∅⊢⌜⌊𝑞⌋⌝𝐴:𝑏andΔ𝑑(𝑎,𝑞);∅⊢𝖼𝗈𝖽𝖾𝐴(⌊𝑞⌋):◻𝑏. Thus every result of the displayed Scheme0-fragment specializer translates to closed-ordinary-context Tstage code; the only free target names are the modal residual variables and modal arithmetic constants recorded in Δ𝑑(𝑎,𝑞).
Proof of Proposition 129.5 — Type preservation for the Scheme0 arithmetic bridge
Proof. Induct on the derivation of 𝑠⊢𝐴𝑎:𝑏𝐴, retaining the equation that defines 𝑞. A numeral specializes to 𝗏𝖺𝗅(𝑛), and a static variable specializes to 𝗏𝖺𝗅(𝑠(𝑥𝑠)); T-MVar types the corresponding modal numeral constant at 𝑏. A dynamic variable specializes to 𝖼𝗈𝖽𝖾(𝑥𝑑), and T-MVar types 𝑥𝑑:𝑏.
In A-Op-S, both operands specialize to recorded numerals and the result is 𝗏𝖺𝗅(𝑛1⊙𝑛2), so the numeral-constant case applies. In A-Op-D, the two induction hypotheses type ⌜⌊𝑞1⌋⌝𝐴 and ⌜⌊𝑞2⌋⌝𝐴 at 𝑏. Rule T-MVar types ¯⊙:𝑏→𝑏→𝑏; two uses of T-App give the translated residual operation type 𝑏. These are all formation rules. In every case, T-Box applies because the ordinary context is empty, yielding the second judgment. ◻
Suppose 𝑠⊢𝐴𝑎:𝑏, 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎,𝑠)=𝑞, and 𝑑 assigns every dynamic variable of 𝑎. Whenever the arithmetic on either side is defined, 𝖾𝗏𝖺𝗅𝐴(|𝑎|𝐴,(𝑠,𝑑))=𝖾𝗏𝖺𝗅𝐴(⌊𝑞⌋,𝑑). Here a residual numeral evaluates to itself, so the right side also covers 𝑞=𝗏𝖺𝗅(𝑛).
Proof of Lemma 129.6 — Arithmetic specialization for both binding times
Proof. Induct on the displayed binding-time derivation, with the assertion quantified over its conclusion 𝑏 and output 𝑞. A numeral evaluates to itself. A static variable is looked up in 𝑠, and a dynamic variable is looked up in 𝑑; these are exactly their specialized outputs. For A-Op-S, both induction hypotheses yield the recorded numerals, and specialization computes the same primitive. For A-Op-D, apply the induction hypothesis separately to each premise, whether its conclusion is 𝑆 or 𝐷. Erasure evaluates the primitive on those two values, while specialization embeds each 𝗏𝖺𝗅(𝑛𝑖) as the residual numeral 𝑛𝑖 and leaves each 𝖼𝗈𝖽𝖾(𝑟𝑖) as 𝑟𝑖. The residual primitive therefore receives the identical pair of values. These are all three leaves, both primitive symbols, and both operation rules. ◻
Suppose 𝑠⊢𝐴𝑎:𝐷 and 𝗌𝗉𝖾𝖼𝗂𝖺𝗅𝗂𝗓𝖾𝐴(𝑎,𝑠)=𝖼𝗈𝖽𝖾(𝑟). For every dynamic environment 𝑑, 𝖾𝗑𝖾𝖼𝐴(𝖼𝗈𝖽𝖾𝐴(𝑟),𝑑)=𝖾𝗏𝖺𝗅𝐴(|𝑎|𝐴,(𝑠,𝑑)) whenever the displayed primitive arithmetic operations are defined.
Proof of Proposition 129.7 — Annotated arithmetic commuting instance
Proof. Apply lemma 129.6 with 𝑞=𝖼𝗈𝖽𝖾(𝑟). Its right side is 𝖾𝗏𝖺𝗅𝐴(𝑟,𝑑), which is equivalent by definition to 𝖾𝗑𝖾𝖼𝐴(𝖼𝗈𝖽𝖾𝐴(𝑟),𝑑). Symmetry gives the displayed orientation. The primitive-definedness condition is unchanged. ◻
Tagless-final staging is another interface. Begin with the initial syntax 𝑡::=𝗅𝗂𝗍(𝑛)∣𝗏𝖺𝗋(𝑥)∣𝗆𝗎𝗅(𝑡,𝑡). For an environment 𝑑, its evaluator has the three equations 𝖾𝗏𝖺𝗅𝗍𝖿(𝗅𝗂𝗍(𝑛),𝑑)=𝑛,𝖾𝗏𝖺𝗅𝗍𝖿(𝗏𝖺𝗋(𝑥),𝑑)=𝑑(𝑥),𝖾𝗏𝖺𝗅𝗍𝖿(𝗆𝗎𝗅(𝑡,𝑢),𝑑)=𝖾𝗏𝖺𝗅𝗍𝖿(𝑡,𝑑)⋅𝖾𝗏𝖺𝗅𝗍𝖿(𝑢,𝑑). Its serializer is the fold that maps a literal to its decimal numeral, a variable to its name, and multiplication to the parenthesized concatenation (𝑠*𝑟). These are two algebras for the same signature 𝗅𝗂𝗍:ℕ→𝑅,𝗏𝖺𝗋:𝖵𝖺𝗋→𝑅,𝗆𝗎𝗅:𝑅→𝑅→𝑅.
The final representation of an initial tree 𝑡 is the polymorphic operation ̂𝑡 that accepts such an algebra and returns its interpretation. The evaluator and serializer are therefore added one at a time by choosing 𝑅=(𝖵𝖺𝗋→ℕ)→ℕ and 𝑅=𝖲𝗍𝗋𝗂𝗇𝗀, respectively. Structural induction gives their exact common representation property.
Proof of Proposition 129.8 — Pure tagless-final representation
Proof. Induct on 𝑡. A literal and a variable use the corresponding algebra operation on both sides. A multiplication node applies the induction hypotheses to its two children and then the same 𝗆𝗎𝗅 operation. These are all three constructors. ◻
Now add a partial-evaluation algebra. Its carrier is 𝑞::=𝗄𝗇𝗈𝗐𝗇(𝑛)∣𝗅𝖺𝗍𝖾𝗋(𝑡),𝗋𝖾𝗂𝖿𝗒(𝗄𝗇𝗈𝗐𝗇(𝑛))=𝗅𝗂𝗍(𝑛),𝗋𝖾𝗂𝖿𝗒(𝗅𝖺𝗍𝖾𝗋(𝑡))=𝑡. Literals are known, variables are later, and multiplication computes on two known inputs: 𝗆𝗎𝗅𝗉𝖾(𝗄𝗇𝗈𝗐𝗇(𝑛1),𝗄𝗇𝗈𝗐𝗇(𝑛2))=𝗄𝗇𝗈𝗐𝗇(𝑛1𝑛2). For every other pair (𝑞1,𝑞2), it residualizes: 𝗆𝗎𝗅𝗉𝖾(𝑞1,𝑞2)=𝗅𝖺𝗍𝖾𝗋(𝗆𝗎𝗅(𝗋𝖾𝗂𝖿𝗒(𝑞1),𝗋𝖾𝗂𝖿𝗒(𝑞2))). For 𝑡0=𝗆𝗎𝗅(𝗅𝗂𝗍(2),𝗆𝗎𝗅(𝗅𝗂𝗍(3),𝗅𝗂𝗍(4))), evaluation returns 24, serialization returns (𝟸*(𝟹*𝟺)), and partial evaluation returns 𝗄𝗇𝗈𝗐𝗇(24). For 𝑡1=𝗆𝗎𝗅(𝗅𝗂𝗍(2),𝗆𝗎𝗅(𝗏𝖺𝗋(𝑥),𝗅𝗂𝗍(3))), partial evaluation returns the same tree under 𝗅𝖺𝗍𝖾𝗋; the algebra performs no reassociation rule.
Proof of Proposition 129.9 — Pure tagless-final partial-evaluation equation
Proof. Induct on 𝑡. Literal and variable cases are their defining equations. For multiplication, apply both induction hypotheses. When both outputs are known, their recorded naturals are the two source evaluations, so multiplying them is sound. Otherwise reification rebuilds multiplication from two reified outputs, and the evaluator uses the induction hypotheses componentwise. These are the two partial-evaluator alternatives. ◻
The course examples separately calculate evaluation, serialization, and de Bruijn partial evaluation. Those examples concern the displayed tagless final algebra; they neither represent arbitrary 𝖳𝗌𝗍𝖺𝗀𝖾 terms nor prove a host optimizer correct [CKcS09].
The optimizing evaluators of Wei, Tan, and Zhong form another separate card [WTZ26]. Their binding-time-annotated object language is interpreted successively by a stateful evaluator, a one-continuation evaluator, a two-continuation evaluator, a delimited-control evaluator, and a CEKM machine. The two continuations separate the rest of the generated expression from the boundary at which pending bindings are inserted. The optimizing evaluator then composes seven independently selectable reflection clauses in this priority order: 𝖺𝗍𝗈𝗆,𝗂𝗇𝗅𝗂𝗇𝖾,𝖿𝗈𝗅𝖽,𝗉𝖺𝗋𝗍𝗂𝖺𝗅𝖲𝗍𝖺𝗍𝗂𝖼,𝗌𝗂𝗆𝗉𝗅𝗂𝖿𝗒𝖢𝗈𝗇𝖽,𝖢𝖲𝖤,𝖣𝖢𝖤, followed by a default clause which introduces a fresh residual let-binding. The ordering is part of this implementation card: changing it can expose a different expression to a later clause.
For example, apply only the CSE clause to the dynamic expression (2⋅3)+(2⋅3). The first multiplication is inserted as 𝑥0. The cache maps the second, syntactically equal pure multiplication to the same 𝑥0, and the default clause names the sum. The printed result is 𝗅𝖾𝗍𝑥0=2⋅3𝗂𝗇𝗅𝖾𝗍𝑥1=𝑥0+𝑥0𝗂𝗇𝑥1. The calculation establishes only the displayed result. It does not prove contextual equivalence of the evaluator families, soundness of every optimization, or compiler correctness for LMS, MetaOCaml, or 𝖳𝗌𝗍𝖺𝗀𝖾.
To connect the final interface back to the modal card, define one modal literal constant ――𝑛::𝑏 for each numeral, a modal variable constant ――𝑥::𝑏 for each object variable, and a modal multiplication constant 𝑚::𝑏→𝑏→𝑏. Then define 𝐺(𝗅𝗂𝗍(𝑛))=𝖻𝗈𝗑――𝑛,𝐺(𝗏𝖺𝗋(𝑥))=𝖻𝗈𝗑――𝑥,𝐺(𝗆𝗎𝗅(𝑡,𝑢))=𝗅𝖾𝗍𝖻𝗈𝗑𝑥=𝐺(𝑡)𝗂𝗇𝗅𝖾𝗍𝖻𝗈𝗑𝑦=𝐺(𝑢)𝗂𝗇𝖻𝗈𝗑(𝑚𝑥𝑦). The two let-boxes sequence the generator’s recursive results; modal substitution yields 𝐺(𝗆𝗎𝗅(𝗅𝗂𝗍(2),𝗅𝗂𝗍(3)))⟶∗𝖻𝗈𝗑(𝑚――2――3). The modal calculus treats these constants symbolically; it contains no numeral, variable-lookup, or multiplication reduction. Changing the outer sequencing order changes the evaluation order of the generators even though the final pure code is alpha-equivalent. With effectful generators, order must instead be preserved by naming the left result before evaluating the right: 𝗅𝖾𝗍𝑎=𝐺(𝑡)𝗂𝗇𝗅𝖾𝗍𝑏=𝐺(𝑢)𝗂𝗇𝖼𝗈𝗆𝖻𝗂𝗇𝖾(𝑎,𝑏). This is a let-insertion calculation, not an equation that permits reordering.
MetaOCaml’s code types, quotation, escape, run, CSP, and let insertion form one system card. Lightweight modular staging instead represents object operations by a host interface and uses host normalization plus explicit code combinators [RO10]. These cards differ from the modal calculus in their syntax, typing judgments, and reduction relations. Neither supplies a theorem about 𝖳𝗌𝗍𝖺𝗀𝖾: such a transfer would require a typed translation and a simulation theorem.
MacoCaml is a third card. Its core types and expressions include 𝜏::=𝖨𝗇𝗍∣𝖴𝗇𝗂𝗍∣𝜏→𝜏∣𝖱𝖾𝖿𝖨𝗇𝗍∣𝖢𝗈𝖽𝖾𝜏,𝑒::=𝑖∣()∣𝑥∣𝜆𝑥:𝜏.𝑒∣𝑒𝑒∣𝗋𝖾𝖿𝑒∣!𝑒∣𝑒:=𝑒∣⟨𝑒⟩∣$𝑒. The source elaboration judgment is 𝜎1;Ω;Γ⊢⋆𝑛𝑒:𝜏⇝𝑒′;𝜎2,⋆∈{𝑐,𝑠,𝑞}. It records the input heap 𝜎1, compile-time evaluation context Ω, type context Γ, integer level 𝑛, compiler mode ⋆, elaborated core expression 𝑒′, and output heap 𝜎2. A local variable declaration records the same level at which it may be used. Mode 𝑐 is ordinary compilation, 𝑠 is compile-time computation inside a top-level splice, and 𝑞 is quotation. The staging rules are
𝜎1;Ω;Γ⊢𝑞𝑛+1𝑒:𝜏⇝𝑒′;𝜎2
𝜎1;Ω;Γ⊢𝑐∨𝑠𝑛⟨𝑒⟩:𝖢𝗈𝖽𝖾𝜏⇝⟨𝑒′⟩;𝜎2
MC-Quote
𝜎1;Ω;Γ⊢𝑠𝑛−1𝑒:𝖢𝗈𝖽𝖾𝜏⇝𝑒′;𝜎2
𝜎1;Ω;Γ⊢𝑞𝑛$𝑒:𝜏⇝$𝑒′;𝜎2
MC-Splice
Here 𝑐∨𝑠 abbreviates one instance for each of the two modes. A top-level splice instead uses compile-time evaluation:
𝜎1;Ω;Γ⊢𝑠𝑛−1𝑒:𝖢𝗈𝖽𝖾𝜏⇝𝑒′;𝜎2𝜎2;Ω⊢𝑒′⟶∗0⟨𝑣⟩;𝜎3
𝜎1;Ω;Γ⊢𝑐𝑛$𝑒:𝜏⇝𝑣;𝜎3
MC-CodeGen
Runtime definitions 𝖽𝖾𝖿𝑘=𝑒 bind 𝑘 at level zero; macro definitions 𝖽𝖾𝖿↓𝑚=𝑒 bind 𝑚 at level minus one. A top-level splice is the compilation interface: typing interleaves with its evaluation, requires a quoted result, and inserts the quoted body into the compiled module. A compiled module contains no top-level splice.
Composition shifts levels explicitly. Importing a module at level zero makes its runtime definitions available at level zero; an 𝗂𝗆𝗉𝗈𝗋𝗍↓ shifts them to level minus one for compile-time use. Macro-bearing modules compose through those leveled imports rather than through textual substitution. Quotation retains binding information. Splice elaboration chooses each binder outside the identifiers occurring in the caller module, quoted value, and generated body before binder insertion. In the paper’s power example the generated parameter is therefore 𝑥1, which does not occur in the caller; the caller’s 𝑥 cannot be captured. The compiled code for exponent five is 𝜆𝑥1.𝑥1⋅(𝑥1⋅(𝑥1⋅(𝑥1⋅(𝑥1⋅1)))), and applying it to three returns 243.
Suppose Γ𝗈𝗄, 𝜎1𝗈𝗄, and 𝜎1;Γ⊢𝑐Ω. If 𝜎1;Ω;Γ⊢⋆𝑛𝑒:𝜏⇝𝑒′;𝜎2, then the core judgment under the empty heap is ∅;Γ⊢𝑛𝑒′:𝜏. Moreover, the elaborated expression has source level shape 𝑒′1 when ⋆=𝑞, and 𝑒′0 otherwise. Thus no location allocated in the compile-time heap is free in compiled core code.
Proof of Theorem 129.10 — MacoCaml elaboration soundness
Proof. This is the exact expression instance of the source elaboration-soundness theorem [XWNY23]. Its simultaneous induction over expression and structure elaboration uses preservation for the evaluation premise of MC-CodeGen; the level-shape conclusion prevents the returned quotation body from capturing a location at the negative typing level. The source proves the corresponding module and structure instances by the same simultaneous induction. ◻
Preservation, progress, and phase distinction belong to this exact level-indexed calculus [XWNY23]. Its quotation/composition interface is neither MetaOCaml execution nor T-Box, so those proofs strengthen neither theorem 129.3 nor theorem 129.4.
The pure Tan–Wei calculus 𝜆|2| is a fourth system card [TW26]. It freezes stages 𝑠∈{𝟙,𝟚} and the surface grammar 𝑡::=()∣𝑛∣𝑥∣𝜆𝑥.𝑡∣𝗅𝖾𝗍𝑥=𝑡𝗂𝗇𝑡∣𝗅𝗂𝖿𝗍𝑡∣𝗋𝗎𝗇𝑡∣𝖺𝗉𝗉𝑠(𝑡,𝑡)∣𝖿𝗂𝗑𝑠𝑡∣𝗂𝖿𝗓𝑠(𝑡,𝑡,𝑡)∣𝑡⊕𝑠𝑡. Evaluation adds the administrative forms and values 𝑔::=𝖼𝗈𝖽𝖾𝑡∣𝗋𝖾𝖿𝗅𝖾𝖼𝗍𝑡∣𝗅𝖾𝗍𝖼𝑥=𝑡𝗂𝗇𝑡∣𝜆𝖼𝑥.𝑡,𝑣::=𝑛∣()∣𝜆𝑥.𝑡∣𝖼𝗈𝖽𝖾𝑡. A pure evaluation context 𝐸 contains the ordinary left-to-right application, operation, fixed-point, conditional, lift, and let frames. A reification context 𝑃 may additionally contain 𝜆𝖼𝑥.[],𝗅𝖾𝗍𝖼𝑥=𝑡𝗂𝗇[],𝗋𝗎𝗇[],𝗂𝖿𝗓𝟚(𝑣,[],𝑡),𝗂𝖿𝗓𝟚(𝑣1,𝑣2,[]). The decisive head step, for a name 𝑥 fresh for 𝑃,𝐸,𝑡, is 𝑃[𝐸[𝗋𝖾𝖿𝗅𝖾𝖼𝗍𝑡]]⟶𝑃[𝗅𝖾𝗍𝖼𝑥=𝑡𝗂𝗇𝐸[𝖼𝗈𝖽𝖾𝑥]]. Thus a reflected fragment is named once at its reification boundary. The freshness premise and the restriction of 𝐸 to ordinary pure frames are what preserve binding and left-to-right evaluation order.
The static card has 𝜖::=⊥∣⊤,𝜏::=𝗎𝗇𝗂𝗍∣𝗇𝖺𝗍∣𝜏1→𝜖𝜏2∣𝗋𝖾𝗉(𝜏)∣𝖿𝗋𝖺𝗀(𝜏),Γ::=∅∣Γ,𝑥𝑠:𝜏. The judgment Γ⊢𝑠𝑡:𝜏∣𝜖 checks a term at a specified stage. The reification judgment Γ⊢𝑡:𝜏∣𝜖 either embeds a pure stage-one term or packages a fragment as complete code:
Γ⊢𝟙𝑡:𝜏∣⊥
Γ⊢𝑡:𝜏∣⊥
TW-Pure
Γ⊢𝟙𝑡:𝖿𝗋𝖺𝗀(𝜏)∣𝜖
Γ⊢𝑡:𝗋𝖾𝗉(𝜏)∣𝜖
TW-Rep
The rules for 𝖼𝗈𝖽𝖾, 𝗋𝖾𝖿𝗅𝖾𝖼𝗍, and inserted bindings expose the control effect:
Γ⊢𝟚𝑡:𝜏∣⊥
Γ⊢𝟙𝖼𝗈𝖽𝖾𝑡:𝗋𝖾𝗉(𝜏)∣⊥
TW-Code
Γ⊢𝟚𝑡:𝜏∣⊥
Γ⊢𝟙𝗋𝖾𝖿𝗅𝖾𝖼𝗍𝑡:𝖿𝗋𝖺𝗀(𝜏)∣⊤
TW-Reflect
Γ⊢𝟚𝑡1:𝜏1∣⊥Γ,𝑥𝟚:𝜏1⊢𝑡2:𝗋𝖾𝗉(𝜏2)∣𝜖𝖶𝖥𝟚(𝜏1)
Γ⊢𝟙𝗅𝖾𝗍𝖼𝑥=𝑡1𝗂𝗇𝑡2:𝗋𝖾𝗉(𝜏2)∣⊥
TW-LetC
In particular, complete code may contain divergence or a generated-stage effect and therefore is not treated as an unrestricted pure fragment. The remaining surface rules propagate the join of premise effects; every stage-two code-producing operator concludes with effect ⊤. Function types at stage two require latent effect ⊥.
Stage erasure |𝑡| changes every stage annotation to 𝟙, deletes lift, run, code, reflect, and 𝜆𝖼, maps inserted 𝗅𝖾𝗍𝖼 to ordinary let, and erases 𝗋𝖾𝗉, 𝖿𝗋𝖺𝗀, and latent effects. For stage-erased types, define the step-indexed value and term interpretations by V[[𝗎𝗇𝗂𝗍]]={(𝑘,(),())∣𝑘∈ℕ},V[[𝗇𝖺𝗍]]={(𝑘,𝑛,𝑛)∣𝑘,𝑛∈ℕ},(𝑘,𝜆𝑥.𝑡1,𝜆𝑥.𝑡2)∈V[[𝜏1→⊥𝜏2]] exactly when, for every 𝑗≤𝑘 and (𝑗,𝑣1,𝑣2)∈V[[𝜏1]], (𝑗,𝖺𝗉𝗉𝟙(𝜆𝑥.𝑡1,𝑣1),𝖺𝗉𝗉𝟙(𝜆𝑥.𝑡2,𝑣2))∈E[[𝜏2]]. Moreover, (𝑘,𝑡1,𝑡2)∈E[[𝜏]] exactly when ∀𝑗<𝑘.∀𝑣1.𝑡1⟶𝑗𝑣1⟹∃𝑣2.𝑡2⟶∗𝑣2∧(𝑘−𝑗,𝑣1,𝑣2)∈V[[𝜏]]. The environment interpretation starts with G[[∅]]={(𝑘,∅,∅)∣𝑘∈ℕ} and extends two substitutions with values related by V at every declaration 𝑥𝟚:𝜏. Write 𝑡1≈𝗅𝗈𝗀𝑡2:𝜏 when the two terms have erased typing Γ⊢𝟚𝑡𝑖:𝜏∣⊥ and all related substitution instances belong to E in both directions.
Contextual equivalence has a narrower observation than equality of printed base results. For every well-typed closing context 𝐶, 𝑡1≈𝖼𝗍𝗑𝑡2:𝜏 means 𝐶[𝑡1] terminates if and only if 𝐶[𝑡2] terminates. Distinct observable base values can be separated by a context, but the definition itself is termination-based.
Proof of Lemma 129.11 — Tan–Wei logical-relation interface
Proof. These are exact source imports: Theorems 5.4, 5.5, 5.8, and 5.3, respectively . The definitions above print their complete signatures. Within Instar/TwoLevelRec/, the Lean declarations are:
The imported proofs cover the compatibility families, substitution, and the reification-context case; no theorem for 𝖳𝗌𝗍𝖺𝗀𝖾, MetaOCaml, or LMS is a consequence. ◻
The extension 𝜆𝗋𝖾𝖿|2| adds locations, stores of natural numbers, 𝗋𝖾𝖿(𝗇𝖺𝗍), and stage-indexed allocation, get, and put. The executing 𝖺𝗅𝗅𝗈𝖼𝟙, 𝗀𝖾𝗍𝟙, and 𝗉𝗎𝗍𝟙 forms may be typed only beneath the stage-𝟚 judgment; the stage-two forms build fragments beneath the stage-𝟙 judgment. Moreover, 𝗋𝗎𝗇 requires a store-free argument. Its world 𝑊⊆ℕ×ℕ is a partial bijection between locations; stores 𝜎1,𝜎2 are related at 𝑊 when they contain equal naturals at every related pair. The value clause for references is (𝑘,𝑊,ℓ1,ℓ2)∈V[[𝗋𝖾𝖿(𝗇𝖺𝗍)]]⟺(ℓ1,ℓ2)∈𝑊. The term clause quantifies over every pair of stores related by 𝑊: a left run terminating in 𝑗<𝑘 steps must be matched on the right by a run to related values and stores at an extension 𝑊′⊇𝑊, with remaining index 𝑘−𝑗. This is the exact Kripke extension of the displayed pure relation, rather than a persistence theorem for host-language references.
A forbidden first-stage reference shows why the restriction is necessary. Allocate 𝑟=0, lift a function whose body increments 𝑟, and finally lift the contents of 𝑟. Lifting the function executes its body during generation, so the generated answer is one; erasure leaves that body beneath a lambda and returns zero. A second counterexample makes evaluation order visible. With a first-stage 𝑟=0, residualize a conditional whose first branch increments and reads 𝑟, and whose second branch only reads 𝑟. Reifying the first branch first produces 𝗂𝖿𝗓(𝑏,1,1); reifying the second first produces 𝗂𝖿𝗓(𝑏,1,0). The erased program selects one branch before its effect, so it has the latter behavior. The accepted repair allocates 𝑟 with 𝖺𝗅𝗅𝗈𝖼𝟚 and uses only stage-two get and put. The first-stage store then remains empty, and generation returns 𝗅𝖾𝗍𝑟=𝖺𝗅𝗅𝗈𝖼𝟙0𝗂𝗇𝗂𝖿𝗓𝟙(𝑏,𝗅𝖾𝗍_=𝗉𝗎𝗍𝟙(𝑟,𝗀𝖾𝗍𝟙𝑟+1)𝗂𝗇𝗀𝖾𝗍𝟙𝑟,𝗀𝖾𝗍𝟙𝑟). Its effects occur only when the generated conditional executes, in the same order as the stage erasure.
In 𝜆|2|, if ∅⊢𝑡1:𝗋𝖾𝗉(𝜏)∣𝜖 and 𝑡1⟶∗𝖼𝗈𝖽𝖾𝑡2, then |𝑡1|≈𝖼𝗍𝗑𝑡2:𝜏 in the empty closing environment. In 𝜆𝗋𝖾𝖿|2|, if ∅⊢𝑡1:𝗋𝖾𝗉(𝜏)∣𝜖 and ⟨∅,𝑡1⟩⟶∗⟨∅,𝖼𝗈𝖽𝖾𝑡2⟩, then the same contextual equivalence holds under the printed stage-two/store-free restrictions.
Proof of Theorem 129.12 — Source-bounded staging-erasure equivalence
Proof. For the pure card, induct on the multistep reduction. Reflexivity gives contextual reflexivity. At a successor step, item 3 of lemma 129.11 gives equivalence of the two erasures; compose it with the induction hypothesis by item 4. At the terminal code value, |𝖼𝗈𝖽𝖾𝑡2|=𝑡2. This is the proof assembly of source Theorems 5.9–5.10 [TW26].
For the reference card, use the world-indexed versions of the fundamental, soundness, one-step, and transitivity results. The initial world and both first-stage stores are empty; the store-free run premise ensures that first-stage reduction never allocates a location. Iteration therefore yields the displayed contextual equivalence. This is source Theorem 6.4 [TW26]. Its world-indexed signature is different from the pure theorem’s signature, so neither result transfers to another staging card without a separate interpretation theorem. ◻
★★☆ Translate the annotated expression 2𝑆+𝐷(𝑥𝐷𝑑⋅𝐷3𝑆) into the displayed modal arithmetic fragment. Derive its type and check the commuting equation at 𝑥=4.
A tower with object program 𝑝, interpreter 𝐼, and meta-interpreter 𝐽 evaluates 𝐽⌜𝐼⌝⌜𝑝⌝. Ordinary execution retains two dispatch layers. The comparison card is Amin–Rompf’s untyped multi-level kernel 𝜆↑↓, not 𝖳𝗌𝗍𝖺𝗀𝖾. Its source and internal syntax is 𝑒::=𝑥∣𝖫𝗂𝗍(𝑛)∣𝖲𝗍𝗋(𝑠)∣𝖫𝖺𝗆(𝑓,𝑥,𝑒)∣𝖠𝗉𝗉(𝑒,𝑒)∣𝖢𝗈𝗇𝗌(𝑒,𝑒)∣𝖫𝖾𝗍(𝑥,𝑒,𝑒)∣𝖨𝖿(𝑒,𝑒,𝑒)∣⊕1(𝑒)∣⊕2(𝑒,𝑒)∣𝖫𝗂𝖿𝗍(𝑒)∣𝖱𝗎𝗇(𝑒,𝑒)∣𝑔,𝑔::=𝖢𝗈𝖽𝖾(𝑒)∣𝖱𝖾𝖿𝗅𝖾𝖼𝗍(𝑒)∣𝖫𝖺𝗆𝖼(𝑓,𝑥,𝑒)∣𝖫𝖾𝗍𝖼(𝑥,𝑒,𝑒),𝑣::=𝖫𝗂𝗍(𝑛)∣𝖲𝗍𝗋(𝑠)∣𝖫𝖺𝗆(𝑓,𝑥,𝑒)∣𝖢𝗈𝗇𝗌(𝑣,𝑣)∣𝖢𝗈𝖽𝖾(𝑒). Here ⊕1 ranges over the three predicates and pair projections, and ⊕2 over addition, subtraction, multiplication, and equality. 𝖱𝖾𝖿𝗅𝖾𝖼𝗍 and 𝖫𝖾𝗍𝖼 implement ordered let insertion; they are not user quotation forms. The level parameter is the first argument of 𝖱𝗎𝗇(𝑏,𝑒). Evaluation of 𝑏 to code emits a residual run; any non-code value executes the reified code at the present level: 𝖾𝗏𝖺𝗅𝑚𝑠(𝜌,𝖱𝗎𝗇(𝑏,𝑒))=𝗋𝖾𝖿𝗅𝖾𝖼𝗍𝖼(𝖱𝗎𝗇(𝑏′,𝑞))𝖾𝗏𝖺𝗅𝑚𝑠(𝜌,𝑏)=𝖢𝗈𝖽𝖾(𝑏′),𝖾𝗏𝖺𝗅𝑚𝑠(𝜌,𝖱𝗎𝗇(𝑏,𝑒))=𝖾𝗏𝖺𝗅𝑚𝑠𝑔(𝜌,𝑞)𝖾𝗏𝖺𝗅𝑚𝑠(𝜌,𝑏)≠𝖢𝗈𝖽𝖾(−). In both equations, 𝑞=𝗋𝖾𝗂𝖿𝗒𝖼(𝖾𝗏𝖺𝗅𝑚𝑠(𝜌,𝑒)). The polymorphic 𝖫𝗂𝖿𝗍 maps a numeral to numeral syntax, a pair componentwise, code to residual 𝖫𝗂𝖿𝗍, and a closure to code by two-level eta expansion. Thus stage polymorphism is operational: the Pink interpreter abstracts over 𝗆𝖺𝗒𝖻𝖾𝖫𝗂𝖿𝗍, instantiated by the identity for 𝖾𝗏𝖺𝗅 and by 𝖫𝗂𝖿𝗍 for 𝖾𝗏𝖺𝗅𝖼. The calculus has no typing judgment that could be imported into 𝖳𝗌𝗍𝖺𝗀𝖾.
For a Pink program 𝑝, write 𝑝𝑠𝑟𝑐 for its quoted S-expression and [[𝑝]] for its translation to administrative normal form in 𝜆↑↓. Define 𝖾𝗏𝖺𝗅1=𝖾𝗏𝖺𝗅,𝖾𝗏𝖺𝗅𝑛+1=𝖾𝗏𝖺𝗅𝑛𝖾𝗏𝖺𝗅𝑠𝑟𝑐. The paper proposes, with experimental rather than formal proof evidence, [[𝖾𝗏𝖺𝗅𝑝𝑠𝑟𝑐]]≈𝖯𝗂𝗇𝗄[[𝑝]],[[𝗋𝗎𝗇0(𝖾𝗏𝖺𝗅𝖼𝑝𝑠𝑟𝑐)]]≈𝖯𝗂𝗇𝗄[[𝑝]],[[𝖾𝗏𝖺𝗅𝖼𝑝𝑠𝑟𝑐]]⇓[[𝑝]],[[(𝖾𝗏𝖺𝗅𝑛𝖾𝗏𝖺𝗅𝖼𝑠𝑟𝑐)𝑝𝑠𝑟𝑐]]⇓[[𝑝]](𝑛≥1). The observation in the first two lines is Pink contextual behavior; the last two demand the exact administrative-normal-form code, which is the claimed optimality. These are Propositions 4.2–4.6 of the source, where the authors state that formal proofs are absent [AR18].
This evidence has a hard boundary. The source supplies experiments rather than a proof of the claimed contextual equations, so it does not prove 𝗋𝗎𝗇(𝖼𝗈𝗅𝗅𝖺𝗉𝗌𝖾(𝐽,𝐼,𝑝))≈𝗍𝗈𝗐𝖾𝗋𝐽⌜𝐼⌝⌜𝑝⌝. Accordingly, no tower-collapse theorem appears in this chapter’s theorem ledger.
Sources and seminar
The principal calculus, its dual-context proofs, and the two-level embedding are those of Davies and Pfenning [DP01]. The staged-reference and tower cards are intentionally source-bounded [TW26, AR18]. No public theorem from those cards transfers to the modal calculus by notation alone.
Suggested first pass.
None of these problems is a prerequisite for a later chapter. Begin with exercise 129.3, then complete exercise 129.8.
★★☆ Construct a boxed exponentiation generator for exponent four. Give every context in its derivation, reduce the generator to a code value, and type the code body under the empty ordinary context.
★★☆ Extend the term grammar with references and propose unrestricted CSP. Exhibit a reference that outlives its allocation stage. State a value restriction that blocks this term; do not claim preservation for the extension.
★★☆ For a fixed dimension two, construct a generator for matrix multiplication whose input entries are modal naturals. Derive the code type of one output entry, then display the four output entries. State the exact point at which unknown dimensions would require dependent types absent from 𝖳𝗌𝗍𝖺𝗀𝖾.
★★☆ Let generators 𝐺1,𝐺2 each append their name to a stage-zero log and return boxed naturals. Calculate the logs produced by left-to-right let insertion and by the reordered nesting. Repair the latter so that it produces the former log and the same residual addition.
★★★ Fix object terms 𝑝:𝗇𝖺𝗍, an interpreter 𝐼:𝖢𝗈𝖽𝖾𝗇𝖺𝗍→𝗇𝖺𝗍, and a meta-interpreter 𝐽:𝖢𝗈𝖽𝖾(𝖢𝗈𝖽𝖾𝗇𝖺𝗍→𝗇𝖺𝗍)→𝖢𝗈𝖽𝖾𝗇𝖺𝗍→𝗇𝖺𝗍. Type the finite expression 𝐽⟨𝐼⟩⟨𝑝⟩. Identify which type is missing for an additional interpreter level and explain why this typing calculation proves no tower-collapse equation.
★★★Practical project.tstage-code-checker Implement in Agda or Kappa a finite checker for the six rule families, modal substitution beneath nested let-box, index decrement and contraction, and exponentiation. Require boxed-modal acceptance, boxed-ordinary rejection, results 7 and 27, and accepted index decrement. Implement the five-rule binding-time card with static and dynamic prints. Replay the ordinary-capture, index-decrement, and static-addition mutants; name respectively the missing T-Box premise, violated substitution invariant, and broken static-operator equation. The model makes no tower or effect claim.