Prerequisites. Direct starred prerequisites: Chapter 127. No later core chapter depends on this route.
A specializer can stop an unfolding computation after a fixed number of steps. The number explains neither why the computation is growing nor which earlier state it resembles. In 𝗀𝗋𝗈𝗐(𝑥)=𝗀𝗋𝗈𝗐(𝗌𝗎𝖼(𝑥)), no two calls are equal, so memoization also misses the obstruction. A supercompiler records a process tree, detects structural growth, and replaces the growing state by a reusable generalization.
Driving constructs a process tree
We use the pure call-by-value language of Jónsson and Nordlander. Fix a finite constructor signature with finite arities and a finite set of primitive operations.
Terms are 𝑒::=𝑛∣𝑥∣𝑔∣𝑒0𝑒1∣𝜆𝑥.𝑒∣𝑘(⃗𝑒)∣𝑒1⊕𝑒2∣𝖼𝖺𝗌𝖾𝑒𝗈𝖿{𝑝𝑖⇒𝑒𝑖}𝑖∣𝗅𝖾𝗍𝑥=𝑒0𝗂𝗇𝑒1∣𝗅𝖾𝗍𝗋𝖾𝖼𝑔=𝑣𝗂𝗇𝑒,𝑝::=𝑛∣𝑘(⃗𝑥). The 𝗅𝖾𝗍𝗋𝖾𝖼 form is source notation, not a seventh core contraction. With a distinguished global 𝖿𝗂𝗑 satisfying 𝐺(𝖿𝗂𝗑)=𝜆𝑓.𝑓(𝜆𝑛.𝖿𝗂𝗑𝑓𝑛), define 𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑒𝗂𝗇𝑒′:=(𝜆ℎ.𝑒′)(𝜆𝑦.𝖿𝗂𝗑(𝜆ℎ.𝜆⃗𝑥.𝑒)𝑦), where ⃗𝑥=(𝑥1,…,𝑥𝑛), the only free variable of 𝜆⃗𝑥.𝑒 may be ℎ, and 𝑦 satisfies 𝑦∉fv(𝑒)∪fv(𝑒′)∪{ℎ,𝑥1,…,𝑥𝑛}. This is the exact macro expansion used here; evaluation and residualization expand it before using the core rules. Values are 𝑣::=𝑛∣𝜆𝑥.𝑒∣𝑘(⃗𝑣). The finite map 𝐺 supplies each global 𝑔’s closed value. Concrete evaluation uses contexts 𝐸::=[]∣𝐸𝑒∣(𝜆𝑥.𝑒)𝐸∣𝑘(⃗𝑣,𝐸,⃗𝑒)∣𝐸⊕𝑒∣𝑛⊕𝐸∣𝖼𝖺𝗌𝖾𝐸𝗈𝖿{𝑝𝑖⇒𝑒𝑖}∣𝗅𝖾𝗍𝑥=𝐸𝗂𝗇𝑒 and, after expanding 𝗅𝖾𝗍𝗋𝖾𝖼, the six left-to-right call-by-value contractions. For a fixed branch list 𝐵={𝑝𝑖⇒𝑒𝑖}𝑖, write 𝖢[𝑢;𝐵]=𝖼𝖺𝗌𝖾𝑢𝗈𝖿𝐵. 𝐸⟨𝑔⟩⟶𝖼𝖻𝗏𝐸⟨𝑣⟩(𝐺(𝑔)=𝑣),𝐸⟨(𝜆𝑥.𝑒)𝑣⟩⟶𝖼𝖻𝗏𝐸⟨𝑒[𝑣/𝑥]⟩,𝐸⟨𝗅𝖾𝗍𝑥=𝑣𝗂𝗇𝑒⟩⟶𝖼𝖻𝗏𝐸⟨𝑒[𝑣/𝑥]⟩,𝐸⟨𝖢[𝑘𝑗(⃗𝑣);𝐵]⟩⟶𝖼𝖻𝗏𝐸⟨𝑒𝑗[⃗𝑣/⃗𝑥𝑗]⟩,𝐸⟨𝖢[𝑛𝑗;𝐵]⟩⟶𝖼𝖻𝗏𝐸⟨𝑒𝑗⟩,𝐸⟨𝑛1⊕𝑛2⟩⟶𝖼𝖻𝗏𝐸⟨𝗉𝗋𝗂𝗆⊕(𝑛1,𝑛2)⟩. A configuration is a pair 𝑅⟨𝑒⟩, where the one-hole strict context 𝑅::=[]∣𝑅𝑒∣𝖼𝖺𝗌𝖾𝑅𝗈𝖿{𝑝𝑖⇒𝑒𝑖}𝑖∣𝑅⊕𝑒∣𝑒⊕𝑅 records work that must finish before its focus. A process edge is labelled by a substitution and is not a concrete evaluation step.
The full driver is the ordered partial function 𝖣𝑅,𝐺,𝜌(𝑒). Here 𝑅⟨𝑒⟩ plugs 𝑒 into 𝑅, 𝑎 ranges over obstructed expressions, and 𝜌 records residual names paired with earlier calls and satisfying the allocation condition stated with A4a–A4c. More precisely, an entry for a configuration 𝑄, whose ordered free-variable vector is ⃗𝑥, has the form 𝜌(ℎ)=𝜆⃗𝑥.𝑄. We abbreviate that assertion by (ℎ,𝑄)∈𝜌. Whenever fv(𝑄) occurs in an argument position, it denotes this fixed ordered vector rather than an unordered set. For the branch list 𝐵={𝑝𝑖⇒𝑒𝑖}𝑖, put 𝐵𝑅𝑥={𝑝𝑖⇒𝖣[]((𝑅⟨𝑒𝑖⟩)[𝑝𝑖/𝑥])}𝑖,𝐵𝑅={𝑝𝑖⇒𝖣[](𝑅⟨𝑒𝑖⟩)}𝑖. The complete ordered rule ledger is: 𝑅1−−𝑅3:𝖣𝑅(𝑛)=𝑅⟨𝑛⟩,𝖣𝑅(𝑥)=𝑅⟨𝑥⟩,𝖣𝑅(𝑔)=𝖣𝖺𝗉𝗉𝑅(𝑔);𝑅4−−𝑅6:𝖣[](𝑘(⃗𝑒))=𝑘(𝖣[](⃗𝑒)),𝖣𝑅(𝑥⃗𝑒)=𝑅⟨𝑥𝖣[](⃗𝑒)⟩,𝖣[](𝜆⃗𝑥.𝑒)=𝜆⃗𝑥.𝖣[](𝑒);𝑅7:𝖣𝑅(𝑛1⊕𝑛2)=𝖣[](𝑅⟨𝑛⟩),𝑛=𝗉𝗋𝗂𝗆⊕(𝑛1,𝑛2);𝑅8:𝖣𝑅(𝑒1⊕𝑒2)=⎧{
{⎨{
{⎩𝖣[](𝑒1)⊕𝖣[](𝑒2),𝑒1⊕𝑒2=𝑎,𝖣𝑅⟨𝑒1⊕[]⟩(𝑒2),𝑒1=𝑛or𝑎,𝖣𝑅⟨[]⊕𝑒2⟩(𝑒1),otherwise;𝑅9−−𝑅10:𝖣𝑅((𝜆⃗𝑥.𝑓)⃗𝑒)=𝖣𝑅(𝗅𝖾𝗍⃗𝑥=⃗𝑒𝗂𝗇𝑓),𝖣𝑅(𝑒𝑒′)=𝖣𝑅⟨[]𝑒′⟩(𝑒);𝑅11−−𝑅12:𝖣𝑅(𝗅𝖾𝗍𝑥=𝑛𝗂𝗇𝑓)=𝖣[](𝑅⟨𝑓[𝑛/𝑥]⟩),𝖣𝑅(𝗅𝖾𝗍𝑥=𝑦𝗂𝗇𝑓)=𝖣[](𝑅⟨𝑓[𝑦/𝑥]⟩), where the last equation requires that 𝑦 was not introduced by a preceding split. For rule R13, let 𝐿=𝗅𝖾𝗍𝑥=𝑒𝗂𝗇𝑓 and 𝑄=𝑥∈𝗌𝗍𝗋𝗂𝖼𝗍(𝑓)∩𝗅𝗂𝗇𝖾𝖺𝗋(𝑓). 𝑅13:𝖣𝑅(𝐿)={𝖣[](𝑅⟨𝑓[𝑒/𝑥]⟩),𝑄,𝗅𝖾𝗍𝑥=𝖣[](𝑒)𝗂𝗇𝖣[](𝑅⟨𝑓⟩),otherwise;𝑅14:𝖣𝑅(𝗅𝖾𝗍𝗋𝖾𝖼𝑔=𝑣𝗂𝗇𝑒)=𝖣[],𝐺′,𝜌(𝑅⟨𝑒⟩),𝐺′=𝐺∪{𝑔↦𝑣};𝑅15−−𝑅17:𝖣𝑅(𝖢[𝑥;𝐵])=𝖢[𝑥;𝐵𝑅𝑥],𝖣𝑅(𝖢[𝑘𝑗(⃗𝑒);𝐵])=𝖣[](𝑅⟨𝗅𝖾𝗍⃗𝑥𝑗=⃗𝑒𝗂𝗇𝑒𝑗⟩),𝖣𝑅(𝖢[𝑛𝑗;𝐵])=𝖣[](𝑅⟨𝑒𝑗⟩);𝑅18−−𝑅20:𝖣𝑅(𝖢[𝑎;𝐵])=𝖢[𝖣[](𝑎);𝐵𝑅],𝖣𝑅(𝖢[𝑒;𝐵])=𝖣𝑅𝖼𝖺𝗌𝖾(𝑒),𝖣𝑅(𝑒)=𝑅⟨𝑒⟩. Here 𝑅𝖼𝖺𝗌𝖾=𝑅⟨𝖢[[];𝐵]⟩ in rule R19. Rules are tried in numerical order. The obstructed grammar is 𝑎::=𝑥∣𝑛⊕𝑎∣𝑎⊕𝑛∣𝑎⊕𝑎∣𝑎⃗𝑒. The strict-variable analysis is the exact syntax-directed function 𝗌𝗍𝗋𝗂𝖼𝗍(𝑥)={𝑥},𝗌𝗍𝗋𝗂𝖼𝗍(𝑛)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑔)=∅,𝗌𝗍𝗋𝗂𝖼𝗍(𝑘(⃗𝑒))=⋃𝑖𝗌𝗍𝗋𝗂𝖼𝗍(𝑒𝑖),𝗌𝗍𝗋𝗂𝖼𝗍(𝜆𝑥.𝑒)=∅,𝗌𝗍𝗋𝗂𝖼𝗍(𝑓𝑒)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑓)∪𝗌𝗍𝗋𝗂𝖼𝗍(𝑒),𝗌𝗍𝗋𝗂𝖼𝗍(𝗅𝖾𝗍𝑥=𝑒𝗂𝗇𝑓)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑒)∪(𝗌𝗍𝗋𝗂𝖼𝗍(𝑓)∖{𝑥}),𝗌𝗍𝗋𝗂𝖼𝗍(𝗅𝖾𝗍𝗋𝖾𝖼𝑔=𝑣𝗂𝗇𝑓)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑓),𝗌𝗍𝗋𝗂𝖼𝗍(𝑒1⊕𝑒2)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑒1)∪𝗌𝗍𝗋𝗂𝖼𝗍(𝑒2),𝗌𝗍𝗋𝗂𝖼𝗍(𝑒𝖼𝖺𝗌𝖾)=𝗌𝗍𝗋𝗂𝖼𝗍(𝑒)∪⋂𝑖(𝗌𝗍𝗋𝗂𝖼𝗍(𝑒𝑖)∖fv(𝑝𝑖)), where 𝑒𝖼𝖺𝗌𝖾=𝖼𝖺𝗌𝖾𝑒𝗈𝖿{𝑝𝑖⇒𝑒𝑖}. A term is linear in 𝑥 when 𝑥 occurs at most once, except that distinct case branches may each contain 𝑥; the case scrutinee and any branch may not both contain it. Let 𝗅𝗂𝗇𝖾𝖺𝗋(𝑓) collect such variables. Rule R13 is the only rule that spends both strictness and linearity. Removing either side condition can move or duplicate a diverging computation across a call-by-value demand.
The application driver must retain all four alternatives. Put ̂𝑔=𝑅⟨𝑔⟩, and write 𝖠𝑅,𝐺,𝜌(𝑔) for 𝖣𝖺𝗉𝗉𝑅(𝑔). The alternatives are tried in order: 𝐴1:𝖠𝑅,𝐺,𝜌(𝑔)=ℎ⃗𝑥if(ℎ,𝑒1)∈𝜌and𝜎𝑒1=̂𝑔;⃗𝑥=𝜎(fv(𝑒1));𝐴2:𝖠𝑅,𝐺,𝜌(𝑔)=̂𝑔if(ℎ,𝑒1)∈𝜌,𝑒1≼̂𝑔≼𝑒1;𝐴3:𝖠𝑅,𝐺,𝜌(𝑔)=[𝖣[](⃗𝑓)/⃗𝑦]𝖣[](𝑓𝑔)if(ℎ,𝑒1)∈𝜌and𝑒1≼̂𝑔;(𝑓𝑔,⃗𝑓,⃗𝑦)=𝗌𝗉𝗅𝗂𝗍(̂𝑔,𝑒1). If none applies, choose a residual name ℎ such that ℎ∉fv(̂𝑔)∪fn(̂𝑔)∪dom(𝜌)∪⋃𝑞∈rng(𝜌)fn(𝑞)∪⋃𝑣∈rng(𝐺)fn(𝑣), and set (𝑔,𝑣)∈𝐺,𝜌′=𝜌∪{ℎ↦𝜆⃗𝑥.̂𝑔},⃗𝑥=fv(̂𝑔),𝑒=𝖣[],𝐺,𝜌′(𝑅⟨𝑣⟩). and use the ordered subalternatives. Here Sub(𝑒) is the finite set of strict proper subexpressions of 𝑒. 𝐴4𝑎:𝖠𝑅,𝐺,𝜌(𝑔)=[𝖣[](⃗𝑓)/⃗𝑦]𝖣[](𝑓𝑔)ifaselected𝑒1∈Sub(𝑒)exists;𝑒1≼̂𝑔and̂𝑔⧸≼𝑒1,and(𝑓𝑔,⃗𝑓,⃗𝑦)=𝗌𝗉𝗅𝗂𝗍(̂𝑔,𝑒1);𝐴4𝑏:𝖠𝑅,𝐺,𝜌(𝑔)=𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑒𝗂𝗇ℎ⃗𝑥ifℎ∈fn(𝑒);𝐴4𝑐:𝖠𝑅,𝐺,𝜌(𝑔)=𝑒otherwise. Alternative A1 is the only fold. Alternative A2 stops at mutual embedding. Alternative A3 is downward generalization; A2 followed on a later visit by A4a supplies upward generalization. Rule A4b closes a residual recursive binding exactly when the name allocated before unfolding occurs in the driven body. Dropping that preallocation loses recursive back edges. These are the application rules of the SC-CBV algorithm used throughout the remainder of the chapter.
The negative premise in A4a is a progress guard: it requires the selected subexpression to embed the call strictly rather than mutually. Syntactic proper-subexpression status alone does not imply this condition, because embedding forgets variable identities. For pairwise distinct variables 𝑥,𝑦,𝑧, the calls 𝑔(𝑥,𝑥) and 𝑔(𝑦,𝑧) mutually embed. Their equal-head split may have general spine 𝑔(𝑧𝑦,𝑥,𝑧𝑧,𝑥), where the two variables are chosen by the fixed enumeration of 𝑍(𝑔(𝑦,𝑧),𝑔(𝑥,𝑥)). This spine has exactly the weight of 𝑔(𝑦,𝑧). Without the guard, the recursive call on that spine need not decrease. With the guard, such a candidate falls through to A4b or A4c; clause adequacy is unchanged, while the strict-descent theorem below becomes valid.
For the first-order process-tree drawings, we use the partial projection 𝖽𝗋𝗂𝗏𝖾0(𝑄)={(𝜃𝑗,𝑄𝑗)}𝑗. Its domain contains a call-by-value beta redex, a constructor case, or an open-variable case at the focus. It is not the full SC-CBV driver: application focus, constructors with nonvalue fields, globals, primitives, let, and expanded 𝗅𝖾𝗍𝗋𝖾𝖼 remain governed by rules R1–R20 above. The local projection has exactly the following rules.
𝖽𝗋𝗂𝗏𝖾0(𝑅⟨(𝜆𝑥.𝑒)𝑣⟩)={([𝑣/𝑥],𝑅⟨𝑒⟩)}
D-Beta
For the branch family B={𝑐𝑖(⃗𝑥𝑖)⇒𝑒𝑖}𝑖∈𝐼, put 𝜃𝑗=[𝑐𝑗(⃗𝑧𝑗)/𝑦] and 𝑄𝑗=𝑅𝜃𝑗⟨𝖼𝖺𝗌𝖾𝑐𝑗(⃗𝑧𝑗)𝗈𝖿B⟩. The two case rules are
𝑗∈𝐼
𝖽𝗋𝗂𝗏𝖾0(𝑅⟨𝖼𝖺𝗌𝖾𝑐𝑗(⃗𝑣)𝗈𝖿B⟩)={([⃗𝑣/⃗𝑥𝑗],𝑅⟨𝑒𝑗⟩)}
D-Case-Known
𝑦isfree𝑗∈𝐼
𝖽𝗋𝗂𝗏𝖾0(𝑅⟨𝖼𝖺𝗌𝖾𝑦𝗈𝖿B⟩)={(𝜃𝑗,𝑄𝑗)}𝑗∈𝐼
D-Case-Open
Compatibility is rule specific. For a beta edge, 𝛿 agrees with a closing value substitution 𝜎 on the free variables of the parent and maps the discharged binder 𝑥 to 𝑣𝜎. For a known-case edge it instead maps every branch binder 𝑥𝑖 to the corresponding component of ⃗𝑣𝜎. For an open-case edge 𝑗, 𝛿 agrees with 𝜎 away from 𝑦, maps ⃗𝑧𝑗 to the fields of 𝜎(𝑦)=𝑐𝑗(⃗𝑤), and satisfies 𝛿(⃗𝑧𝑗)=⃗𝑤. The edge observation is {𝑄𝜎⟶𝖼𝖻𝗏𝑄′𝛿,forD-BetaandD-Case-Known,𝑄𝜎=𝑄′𝛿,forD-Case-Open. The first line is a concrete contraction, not syntactic equality. In the open-case line, 𝑄′ retains the now-known case expression: the edge only refines 𝑦’s constructor shape. A subsequent D-Case-Known edge performs the contraction. This separation is what makes the equality true.
Driving 𝖼𝖺𝗌𝖾𝑦𝗈𝖿{𝖭𝗂𝗅⇒𝖭𝗂𝗅;𝖢𝗈𝗇𝗌(𝑎,𝑧)⇒𝖢𝗈𝗇𝗌(𝑎,𝑧)} creates two children. Their edge substitutions describe all and only outer constructor shapes that the unknown 𝑦 may acquire.
If 𝖽𝗋𝗂𝗏𝖾0(𝑄)={(𝜃𝑗,𝑄𝑗)}𝑗∈𝐽, and every open case reached by the displayed derivation has an exhaustive, disjoint constructor branch family for the closed value supplied by 𝜎, then every substitution 𝜎 mapping the free variables of 𝑄 to closed values makes 𝑄𝜎 closed and selects exactly one compatible child. Conversely, each compatible child denotes the selected call-by-value behavior of 𝑄𝜎.
Proof. Proceed by the last driving rule. In D-Beta, substitution is the call-by-value beta step. D-Case-Known selects the constructor’s unique branch. In D-Case-Open, exhaustiveness gives an outer constructor shape for 𝜎(𝑦), and disjointness makes it unique; its fields define the unique compatible extension. Applying that extension to the refined child gives the uncontracted parent instance literally. A subsequent node uses D-Case-Known. These are the three rule families of 𝖽𝗋𝗂𝗏𝖾0. No coverage claim is made for the full grammar; R1–R20 supply that separate driver. ◻
★☆☆ Suppose append recurses on its first argument. Drive the first two nodes of 𝖺𝗉𝗉𝖾𝗇𝖽(𝑥,𝖢𝗈𝗇𝗌(𝑏,𝖭𝗂𝗅)). Give both substitutions at the open case and the residual expression at each leaf.
The whistle is the test that reports when an earlier configuration embeds in the configuration being driven. The name denotes only an alarm for structural growth: it proves neither semantic equivalence nor that the later configuration may be folded to the earlier one.
Two configurations are variants, written 𝑄≡𝛼𝑄′, when a bijective renaming of free variables maps one to the other. A later variant folds to the earlier node and supplies a residual recursive call.
If 𝑄′=𝑄𝜋 for a variable renaming 𝜋, replacing the subtree rooted at 𝑄′ by a call to the residual function for 𝑄, with arguments 𝜋, preserves the returned value of every closing instance. The residual named call is accounted for separately by the improvement relation of definition 128.6; this lemma asserts no equality of named-call counts.
Proof. The residual equation for 𝑄 abstracts precisely its free variables. Instantiation by 𝜋 alpha-renames that equation to the one required at 𝑄′. Unfolding the residual call exposes that instantiated body. Induction on a finite evaluation derivation then matches every source contraction with the corresponding contraction of the unfolded equation; alpha-renaming preserves the selected rule and substitution. Both closed instances therefore return the same value. Named residual calls are not counted by this local argument. ◻
Folding does not catch 𝑥,𝖲(𝑥),𝖲(𝖲(𝑥)),…. The homeomorphic embedding relation on constructor trees is generated by
𝑥≼𝑦
Emb-Var
𝑛1≼𝑛2
Emb-Num
𝑠≼𝑡𝑖
𝑠≼𝑐(𝑡1,…,𝑡𝑘)
Emb-Dive
𝑠𝑖≼𝑡𝑖(1≤𝑖≤𝑘)
𝑐(𝑠1,…,𝑠𝑘)≼𝑐(𝑡1,…,𝑡𝑘)
Emb-Couple
Variables embed variables and numerals embed numerals irrespective of their names or values; distinct constructor heads do not couple. Encode a configuration by a tree with a distinguished configuration-root label and ordered children for its context and focus, and use the displayed relation on that tree. Thus 𝑥≼𝖲(𝑥), but 𝖲(𝑥)⧸≼𝖹.
Fix a finite constructor signature and a finite global map 𝐺. Every infinite sequence of finite configurations whose global names lie in dom(𝐺) contains 𝑖<𝑗 with 𝑄𝑖≼𝑄𝑗. Consequently an infinite process-tree branch contains a later configuration that raises the embedding whistle.
Proof. Let 𝑋 be a set with a reflexive, transitive relation ≤𝑋. The pair (𝑋,≤𝑋) is a well-quasi-order when every infinite sequence 𝑥0,𝑥1,… contains indices 𝑖<𝑗 with 𝑥𝑖≤𝑋𝑥𝑗. We import the following combinatorial theorem. If (𝑋,≤𝑋) is a well-quasi-order, then its finite rooted labelled trees are well-quasi-ordered by homeomorphic embedding, where coupling compares root labels by ≤𝑋 and corresponding children, and diving compares a tree with a descendant. Kruskal’s proof of this statement occupies physical pages 5–15, printed pages 214–224 .
Let 𝐿 contain the configuration-root label, the finitely many term and context tags, one label for every member of dom(𝐺), one numeral label, and one variable label. Equality makes the finite set 𝐿 a well-quasi-order: an infinite label sequence repeats a label by the infinite pigeonhole principle. Encode 𝑄 as the ordered 𝐿-labelled tree described before the theorem. A structural induction on the imported tree-embedding derivation proves 𝐸(𝑄)≼𝐸(𝑄′)⟹𝑄≼𝑄′. The coupling case is Emb-Couple; the descendant case is Emb-Dive; and the two collapsed leaf cases are Emb-Var and Emb-Num. Kruskal therefore supplies 𝑖<𝑗 with 𝐸(𝑄𝑖)≼𝐸(𝑄𝑗), and the displayed implication supplies 𝑄𝑖≼𝑄𝑗. An infinite process-tree branch is such a sequence, so its later member raises the whistle against the earlier member. No termination theorem for a program transformer is imported here.
The finite-label hypothesis cannot be removed. For pairwise distinct nullary labels ℓ0,ℓ1,…, the one-node trees ℓ0,ℓ1,… form an infinite sequence with no embedded pair, because neither diving nor equal-root coupling applies. ◻
Stopping at a whistle residualizes the whole growing state. Instead compute a most-specific generalization, the least general tree having both states as substitution instances, in a first-order term algebra. Let TΣ be the finite trees whose internal nodes are the constructors, term-former tags, and context-former tags of the SC-CBV signature. Before encoding a configuration, alpha-rename every binder apart, replace its bound occurrences by de Bruijn indices, and erase its source name from the binder node. Free source variables remain first-order leaves. Substitutions below act only on those free-variable leaves. They are not capture-avoiding substitutions on raw source terms.
For 𝑠,𝑡∈TΣ, the operation 𝗆𝗌𝗀(𝑠,𝑡)=(𝑔,𝜎,𝜏) satisfies 𝑔𝜎=𝑠 and 𝑔𝜏=𝑡. Fix an infinite variable set 𝑍(𝑠,𝑡) disjoint from fv(𝑠)∪fv(𝑡). Equal heads are generalized recursively. At the first unequal pair (𝑢,𝑣), choose the first unused 𝑧𝑢,𝑣∈𝑍(𝑠,𝑡), store (𝑢,𝑣)↦𝑧𝑢,𝑣, and reuse 𝑧𝑢,𝑣 at every repeated disagreement pair. For example, with 𝑧∈𝑍(𝗌𝗎𝖼(𝑥),𝗌𝗎𝖼(𝗌𝗎𝖼(𝑥))), 𝗆𝗌𝗀(𝗌𝗎𝖼(𝑥),𝗌𝗎𝖼(𝗌𝗎𝖼(𝑥)))=(𝗌𝗎𝖼(𝑧),[𝑥/𝑧],[𝗌𝗎𝖼(𝑥)/𝑧]).
Write a uniform term as 𝑠(⃗𝑒). If 𝗆𝗌𝗀(𝑠(⃗𝑒1),𝑠′(⃗𝑒2))=(𝑡𝑔,𝜃1,𝜃2), the exact split alternatives are 𝗌𝗉𝗅𝗂𝗍(𝑠(⃗𝑒1),𝑠′(⃗𝑒2))={(𝑡𝑔,rng(𝜃1),dom(𝜃1)),𝑠=𝑠′,(𝑠(⃗𝑥),⃗𝑒1,⃗𝑥),𝑠≠𝑠′, where the components of ⃗𝑥 are pairwise distinct and lie outside fv(𝑠(⃗𝑒1))∪fv(𝑠′(⃗𝑒2)). The first alternative preserves a nontrivial common spine; the second splits the first term along its spine when root disagreement would make the msg a single variable. The application-driver alternatives use this operation for upward and downward generalization. Rule R13’s strictness condition prevents the reassembly from moving a possibly divergent argument out of a call-by-value position.
The termination argument needs a weight that distinguishes a variable introduced by splitting from the expression it replaces. Give every numeral, global or residual name, bound-variable occurrence, and source-variable occurrence weight two. Give every variable introduced by 𝗌𝗉𝗅𝗂𝗍 weight one. For every other syntax former 𝑠, including a vector let treated as one former, put 𝗐𝗍(𝑠(𝑡1,…,𝑡𝑘))=1+𝑘∑𝑖=1𝗐𝗍(𝑡𝑖). Alpha-renaming preserves the source-or-split tag. The variable chosen by 𝗌𝗉𝗅𝗂𝗍 has weight one, so replacing a weight-two atom or a composite by that variable strictly decreases weight. Every proper subexpression has smaller weight than its parent. Let 𝜅(𝑡) be the number of case-expression nodes in 𝑡. A pattern contains no case node, so applying a constructor-pattern substitution cannot increase 𝜅.
For 𝑠,𝑡∈TΣ, 𝗆𝗌𝗀(𝑠,𝑡)=(𝑔,𝜎,𝜏) terminates, satisfies 𝑔𝜎=𝑠 and 𝑔𝜏=𝑡, and is most specific: if ℎ𝜎′=𝑠 and ℎ𝜏′=𝑡, then ℎ𝛿=𝑔 for some 𝛿, up to bijective renaming of the variables chosen from 𝑍(𝑠,𝑡). Moreover, every split selected by A3 or A4a satisfies 𝗌𝗉𝗅𝗂𝗍(𝑠,𝑡)=(𝑓𝑔,⃗𝑓,⃗𝑦),𝗐𝗍(𝑓𝑔)<𝗐𝗍(𝑠),∀𝑓𝑖∈⃗𝑓.𝗐𝗍(𝑓𝑖)<𝗐𝗍(𝑠).
Proof. Induct on the ordinary node count of 𝑠 plus that of 𝑡, with the finite disagreement table threaded through the recursive calls. A table hit returns its stored variable without a recursive call. Suppose 𝑠=𝑐(𝑠1,…,𝑠𝑘) and 𝑡=𝑐(𝑡1,…,𝑡𝑘). For each integer 𝑖 with 1≤𝑖≤𝑘, process the children from left to right. The induction hypothesis gives 𝗆𝗌𝗀(𝑠𝑖,𝑡𝑖)=(𝑔𝑖,𝜎𝑖,𝜏𝑖) at the table produced by the preceding children. Threading makes 𝜎𝑖 and 𝜎𝑗, and likewise 𝜏𝑖 and 𝜏𝑗, agree on every shared domain variable. Hence the following unions are functions: 𝑔=𝑐(𝑔1,…,𝑔𝑘),𝜎=𝑘⋃𝑖=1𝜎𝑖,𝜏=𝑘⋃𝑖=1𝜏𝑖. Then 𝑔𝜎=𝑠 and 𝑔𝜏=𝑡 by the induction equations for every child. If a common generalization has a variable at its root, map that variable to 𝑔. Otherwise its root must be 𝑐; it restricts to a common generalization at each child, so the induction factorizations combine through the same root. This treats every equal-head arity.
For unequal heads the chosen variable 𝑧𝑢,𝑣 with two singleton substitutions has the required equations. Any common generalization must place a variable at that disagreement, so mapping it to 𝑧𝑢,𝑣 defines 𝛿. Memoized disagreement pairs force the same choice at repeated positions and preserve the factorization. Equal heads recurse only on strict child pairs, and unequal heads or table hits stop; hence the node-count induction also proves termination.
It remains to prove the weight assertion. Every selected split has 𝑡≼𝑠 and 𝑠⧸≼𝑡: in A3 the first relation is its side condition and the second follows because the earlier A2 test failed; in A4a they are the two displayed side conditions. In the equal-head arm of 𝗌𝗉𝗅𝗂𝗍, the generalization keeps the common root. Every range member of its first witness substitution is a proper subexpression of 𝑠. If every disagreement on the 𝑠-side were a weight-one split variable, then the corresponding 𝑡-side subterm would also be a variable: no composite tree embeds a variable leaf. Coupling the common nodes and applying Emb-Var at those disagreements would derive 𝑠≼𝑡, contrary to strictness. Hence at least one disagreement replaces a weight-two atom or a composite subexpression by a weight-one split variable. Consequently both the generalization and every range member have weight strictly below 𝗐𝗍(𝑠).
In the unequal-head arm, 𝑠=𝑠0(𝑒1,…,𝑒𝑘) is a selected application configuration and therefore has at least one immediate component. The configuration encoding exposes the selected global atom in one such component. The result 𝑠0(𝑦1,…,𝑦𝑘) replaces every immediate component by a weight-one split variable, while the component containing the global atom has weight at least two. Hence the result has smaller weight, and every 𝑒𝑖 is a proper subexpression of 𝑠. These are exactly the two split arms used by A3 and A4a. ◻
Aggressively folding 𝖼𝖺𝗌𝖾𝑥𝗈𝖿⋯ to an ancestor whose scrutinee is 𝖲(𝑥) discards the zero branch. The variant test rejects the fold; embedding raises a whistle; generalization retains the constructor distinction. Embedding is therefore a trigger, not a folding criterion.
Let 𝐻 range over one-hole SC-CBV term contexts, let 𝑘,𝑘′ range over ℕ, and let 𝑣,𝑣′ range over closed values. The cost comparison counts only calls of named recursive functions.
Write 𝑒⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣 when closed call-by-value evaluation returns 𝑣 after exactly 𝑘 such calls; beta, constructor, primitive, let, and case contractions are not counted. Say that 𝑒 terminates when 𝑒⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣 for some 𝑘,𝑣. Write closes(𝐻;𝑒,𝑒′) when both 𝐻⟨𝑒⟩ and 𝐻⟨𝑒′⟩ are closed. For open terms 𝑒,𝑒′, an operational approximation preserves termination in every closing context, an improvement also does not increase named-call cost, and a strong improvement combines improvement with termination equivalence. Precisely, 𝑒⊑𝗈𝗉𝑒′⟺∀𝐻.closes(𝐻;𝑒,𝑒′)∧∃𝑘,𝑣.𝐻⟨𝑒⟩⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣⟹∃𝑘′,𝑣′.𝐻⟨𝑒′⟩⇓𝑘′𝖼𝖺𝗅𝗅𝗌𝑣′,𝑒⪯𝗂𝗆𝗉𝑒′⟺∀𝐻,𝑘,𝑣.closes(𝐻;𝑒,𝑒′)∧𝐻⟨𝑒⟩⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣⟹∃𝑘′≤𝑘,𝑣′.𝐻⟨𝑒′⟩⇓𝑘′𝖼𝖺𝗅𝗅𝗌𝑣′,𝑒⪯𝗌𝑒′⟺𝑒⪯𝗂𝗆𝗉𝑒′∧𝑒⊑𝗈𝗉𝑒′∧𝑒′⊑𝗈𝗉𝑒. The relation cost equivalence, written 𝑒≃𝖼𝗈𝗌𝗍𝑒′, holds when both 𝑒⪯𝗂𝗆𝗉𝑒′ and 𝑒′⪯𝗂𝗆𝗉𝑒. Cost equivalence implies strong improvement in either orientation. The result 𝑣′ is existential because the observation is termination in every closing context; a context that distinguishes observable constructors supplies the corresponding result test. Thus ⪯𝗌 is Sands’s strong-improvement preorder, not the homeomorphic-embedding relation ≼.
The contextual quantifiers in the definition provide the nonrecursive algebra, but replacing a recursive body must account for every dynamically reached call. Lemma 128.7 proves the contextual algebra. Lemma 128.8 lifts one body improvement through every recursive call, and lemma 128.9 relates a memo entry whose name satisfies the allocation condition to the corresponding local recursive binding. The clause lemma then proves one complete driver step. The descent lemma supplies the well-founded induction that assembles those local steps in theorem 128.14.
Let 𝑒,𝑒′,𝑒″, and 𝑏 be SC-CBV terms. Let 𝐶 be a finite multi-hole term context, let 𝜋 be a capture-avoiding bijective renaming, let ℎ be a residual function name, and let ⃗𝑥 be a finite vector of pairwise distinct variables.
Strong improvement is reflexive and transitive.
If 𝑒⪯𝗌𝑒′, then 𝐶[𝑒]⪯𝗌𝐶[𝑒′], with the replacement made in any fixed collection of holes.
𝑒≃𝖼𝗈𝗌𝗍𝑒𝜋.
If 𝑒⟶𝖼𝖻𝗏𝑒′, then 𝑒⪯𝗌𝑒′. The same conclusion holds for the multi-argument beta-to-let and known-case-to-let equations in the driver.
Proof of Lemma 128.7 — Local strong-improvement laws
Proof. For reflexivity, reuse the given evaluation derivation with the same call count. For transitivity, compose the two existential evaluation witnesses; the inequalities compose by transitivity of ≤, and the two directions of operational approximation compose separately.
For congruence, fix a closing observation context 𝐻. Replacing the selected holes turns 𝐻⟨𝐶[−]⟩ into another closing context for the original pair. Apply the assumed improvement and both assumed termination implications to that composite context. This proves all three conjuncts of strong improvement. Repeating the one-hole argument proves the finite multi-hole form.
Renaming transports an evaluation derivation rule by rule. Binders are renamed before substitution, constructor and global tags are unchanged, and the named-call count is unchanged. Applying the inverse renaming transports the derivation back, which proves cost equivalence.
For a contraction 𝑒⟶𝖼𝖻𝗏𝑒′, splice the contraction in front of any terminating derivation for the contractum. Conversely, invert the unique first step of a terminating derivation for the redex. The two derivations have equal named-call cost except at a global unfolding, where the redex derivation has one additional named call. Thus the contractum never uses more calls, and termination is equivalent. Multi-argument beta and the known-constructor case evaluate the same arguments from left to right and then reach the same simultaneous-substitution instance; induction on the argument vector gives the stated equations.
Finally expand 𝗅𝖾𝗍𝗋𝖾𝖼. Because ℎ is absent from 𝑒, the outer beta substitution changes no occurrence of 𝑒. The administrative beta and fix contractions are not named calls, so the two evaluation derivations have equal named-call cost in both directions. ◻
Let ℎ be a residual function name, let ⃗𝑥=(𝑥1,…,𝑥𝑛) be pairwise distinct variables, and let 𝑏0,𝑏1 be SC-CBV terms satisfying fv(𝑏0)∪fv(𝑏1)⊆{ℎ,𝑥1,…,𝑥𝑛}. Put L𝑖(𝑡)=𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑏𝑖𝗂𝗇𝑡 for 𝑖∈{0,1}. If L0(𝑏0)⪯𝗌L0(𝑏1), then L0(𝑡)⪯𝗌L1(𝑡) for every term 𝑡.
Proof of Lemma 128.8 — Local recursive replacement
Proof. The decisive case is a dynamic call to ℎ: changing only its first unfolding leaves recursive calls under the old binding. We therefore induct on the named-call cost of a finite evaluation derivation, with derivation height as a secondary measure.
Fix a closing observation context 𝐻. For the improvement direction, induct lexicographically on (𝑘,𝑑), where 𝑘 is the named-call cost of a derivation of 𝐻⟨L0(𝑡)⟩ and 𝑑 is its height. Copy a rule that is not a call to ℎ. A premise of equal call cost has smaller height; a premise below any named call has smaller call cost. The induction hypotheses therefore transform every such premise.
At a call ℎ⃗𝑣, the call rule spends one named call and evaluates an instance 𝑏0[⃗𝑣/⃗𝑥] under L0. Apply the assumed body improvement in the closing context consisting of the actual arguments, the evaluation prefix, and the continuation. It gives a derivation of 𝑏1[⃗𝑣/⃗𝑥] under L0 with no larger cost. That cost is strictly smaller than the cost of the original call node, because the call node itself contributed one. The outer induction transforms the supplied derivation from binding L0 to binding L1. Reattach the call rule, prefix, and continuation. Summing premise costs shows that the complete transformed derivation uses no more named calls. This proves improvement and forward operational approximation.
For reverse operational approximation, start with a terminating derivation for L1(𝑡) in the closing context 𝐻, and use the same lexicographic measure. At a call to ℎ, first apply the induction hypothesis to its body derivation; the call node contributes one, so that body has smaller cost. This gives a terminating instance of 𝑏1 under L0. The reverse operational-approximation conjunct of the assumed body relation then gives a terminating instance of 𝑏0 under L0. Reattach the call rule. The noncall cases copy their final rule as in the forward construction. Thus termination is preserved in the reverse direction. The improvement and two approximation results are the three conjuncts of strong improvement. ◻
Let 𝑢,𝑢1,𝑞 be SC-CBV terms, let ℎ be a residual function name, and let 𝜌 be a finite closing memo environment. Let 𝐺 be a finite global map, let 𝑅 be a strict context, let 𝑔 be a global name, and let 𝑣 be a closed value with 𝐺(𝑔)=𝑣. Suppose 𝑢=𝑅⟨𝑔⟩,𝑢1=𝑅⟨𝑣⟩, so that 𝑢⟶𝖼𝖻𝗏𝑢1 is one named global unfolding. Suppose also that ⃗𝑥 is the ordered list fv(𝑢), ℎ∉fv(𝑢)∪fn(𝑢)∪fv(𝑢1)∪fn(𝑢1)∪dom(𝜌), and every free occurrence of ℎ in 𝑞 is a saturated call ℎ𝜋(⃗𝑥) for a bijective renaming 𝜋 of ⃗𝑥. Let 𝜌′ extend 𝜌 by mapping ℎ to 𝜆⃗𝑥.𝑢. Then 𝜌′(𝑞)≃𝖼𝗈𝗌𝗍𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑢1𝗂𝗇𝜌(𝑞),𝑢≃𝖼𝗈𝗌𝗍𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑢1𝗂𝗇ℎ⃗𝑥.
Proof. For the second equation, the displayed disjointness condition for ℎ first inserts the unused binding around 𝑢. Inside that binding, the left program performs the named global unfolding 𝑢⟶𝖼𝖻𝗏𝑢1; the right program performs one named call to ℎ and then beta-reduces to the same 𝑢1. Thus every closing evaluation has a mate with the same result and named-call count, in both directions.
For the first equation, enumerate the finitely many free occurrences of ℎ in 𝑞. Closing by 𝜌′ replaces the occurrence ℎ𝜋(⃗𝑥) by (𝜆⃗𝑥.𝑢)𝜋(⃗𝑥), which beta-reduces to 𝑢𝜋. Under the displayed letrec, the corresponding call to ℎ unfolds to 𝑢1𝜋. The first part of the argument, renamed by 𝜋, gives a cost-equivalent replacement at that occurrence. Apply finite-hole congruence from lemma 128.7 to all occurrences. All other variables are closed by the common map 𝜌, so the resulting terms are exactly the two terms displayed in the statement. ◻
For a residual term 𝑞, write 𝜌(𝑞) for the simultaneous residual-name closing operation: each name ℎ in the finite domain of 𝜌 is replaced by the closed abstraction 𝜌(ℎ). The allocation condition beside A4a–A4c makes the simultaneous operation capture avoiding; it does not recursively reapply 𝜌 inside its own range.
Fix an instance 𝐼 of one selected equation among R1–R20 or A1–A4c with outer state (𝑅𝐼,𝐺𝐼,𝜌𝐼,𝑒𝐼). Put 𝐿𝐼=𝑅𝐼⟨𝑒𝐼⟩, and write 𝑃𝐼[𝑞1,…,𝑞𝑚] for its right-hand side with the 𝑚 recursive driver calls replaced by holes. The 𝑗-th recursive call has its own state (𝑅𝐼,𝑗,𝐺𝐼,𝑗,𝜌𝐼,𝑗,𝑒𝐼,𝑗) and input configuration 𝐿𝐼,𝑗=𝑅𝐼,𝑗⟨𝑒𝐼,𝑗⟩. Suppose the range of every 𝜌𝐼,𝑗 is closed, (fv(𝐿𝐼,𝑗)∪fn(𝐿𝐼,𝑗))∩dom(𝜌𝐼,𝑗)=∅, and 𝐿𝐼,𝑗⪯𝗌𝜌𝐼,𝑗(𝑞𝑗) for every integer 𝑗 with 1≤𝑗≤𝑚. Suppose also that the range of 𝜌𝐼 is closed and (fv(𝐿𝐼)∪fn(𝐿𝐼))∩dom(𝜌𝐼)=∅. Then 𝐿𝐼⪯𝗌𝜌𝐼(𝑃𝐼[𝑞1,…,𝑞𝑚]). Here 𝑚=0 is permitted. The selected clause includes every side condition printed in its rule, including the strict–linear condition of R13, the split witnesses of A3 and A4a, and the occurrence test of A4b.
Proof of Lemma 128.10 — Clause adequacy for the full driver
Proof. Apply the congruence and transitivity parts of lemma 128.7 to the state-indexed recursive hypotheses. It remains to check the noncongruence step selected by each rule family. All observations below use the named-call cost of definition 128.6; no step-counting or value-equality surrogate is introduced.
Rules R1–R6 and R20 only plug a value, variable, constructor, lambda, or obstructed expression into the recorded context. Rule R7 performs the primitive contraction. Rules R8, R10, R18, and R19 expose exactly the demanded call-by-value evaluation context. Rule R9 replaces multi-argument beta reduction by call-by-value lets; both forms first evaluate the arguments from left to right and then evaluate the same simultaneous substitution instance. Rules R11, R12, R16, and R17 perform the displayed let or case contraction. Rule R15 refines the scrutinee constructor and binds precisely the pattern fields selected by that constructor.
For the substitution arm of R13, strictness of 𝑥 in 𝑓 ensures that evaluation of 𝑒 is demanded before the result of 𝑓 is returned, and linearity ensures that the substitution creates at most one demand for 𝑒. Hence it neither removes nor duplicates a possibly diverging call-by-value computation. The other arm leaves the call-by-value let in the residual term. Rule R14 changes the global environment by the displayed recursive value and then drives the body; unfolding that global has exactly the displayed letrec equation.
For A1, suppose 𝜌(ℎ)=𝜆⃗𝑥.𝑄 and ̂𝑔=𝑄𝜋. Closing the emitted fold gives 𝜌(ℎ𝜋(⃗𝑥))=(𝜆⃗𝑥.𝑄)𝜋(⃗𝑥)⟶𝖼𝖻𝗏𝑄𝜋=̂𝑔. The beta contraction costs no named call, and alpha-renaming preserves every later call count by lemma 128.7; hence the fold is cost equivalent to the selected configuration. Rule A2 is the identity residualization at mutual embedding. In A3 and A4a, the equations 𝑓𝑔[⃗𝑓/⃗𝑦]=̂𝑔 supplied by lemma 128.5 and the definition of 𝗌𝗉𝗅𝗂𝗍 reassemble the selected configuration; the recursive hypotheses then apply to 𝖣[](𝑓𝑔) and every 𝖣[](𝑓𝑖). The recursive case A4b spends the state indices. Write ̂𝑔=𝑅⟨𝑔⟩, choose 𝐺(𝑔)=𝑣, put ⃗𝑥=fv(̂𝑔), and let 𝜌′=𝜌∪{ℎ↦𝜆⃗𝑥.̂𝑔},𝑞=𝖣[],𝐺,𝜌′(𝑅⟨𝑣⟩). The allocation condition for ℎ and abstraction of the complete ordered free-variable list make the new range entry closed. The recursive hypothesis is therefore the state-correct assertion 𝑅⟨𝑣⟩⪯𝗌𝜌′(𝑞), not the ill-scoped assertion with 𝜌(𝑞). Put 𝑢=𝑅⟨𝑔⟩, 𝑢1=𝑅⟨𝑣⟩, and L0(𝑡)=𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝑢1𝗂𝗇𝑡,L1(𝑡)=𝗅𝖾𝗍𝗋𝖾𝖼ℎ=𝜆⃗𝑥.𝜌(𝑞)𝗂𝗇𝑡. The global rule in the evaluation context gives 𝑢⟶𝖼𝖻𝗏𝑢1. Every occurrence of the residual name ℎ emitted while driving 𝑞 is a saturated call at a renaming of the ordered vector ⃗𝑥. The first equation of lemma 128.9 therefore gives 𝜌′(𝑞)⪯𝗌L0(𝜌(𝑞)). The unused-binding equation and the recursive hypothesis give the annotated body chain L0(𝑢1)⪯𝗌unusedbinding𝑢1⪯𝗌recursivehypothesis𝜌′(𝑞)⪯𝗌allocationbridgeL0(𝜌(𝑞)). This is the body premise of lemma 128.8. That lemma yields L0(ℎ⃗𝑥)⪯𝗌L1(ℎ⃗𝑥). The second equation of lemma 128.9 gives 𝑢≃𝖼𝗈𝗌𝗍L0(ℎ⃗𝑥). Compose this equivalence with the recursive-replacement conclusion. The resulting left side is 𝑢=̂𝑔, and its right side is exactly the A4b residual under the outer closing map 𝜌.
In A4c, ℎ∉fn(𝑒), so removing the unused allocation changes neither evaluation nor named-call cost. These cases exhaust the ordered ledger. Every use of a recursive result is indexed by its own (𝑅𝐼,𝑗,𝐺𝐼,𝑗,𝜌𝐼,𝑗), and the only change of closing map is the allocation of ℎ treated above. The displayed state-indexed clause follows. ◻
An initial state 𝖣𝑅,𝐺,𝜌(𝑒) is admissible when the constructor and global signatures are finite; constructor arities agree at every occurrence; every case family is finite, exhaustive, and has disjoint patterns; and every global in the transitive syntactic call closure of 𝑅⟨𝑒⟩, 𝐺, and the range of 𝜌 has one closed value in 𝐺. Binders are pairwise distinct after alpha-renaming. Fix an enumeration of residual function names. At a state (𝑅′,𝐺′,𝜌′,𝑒′), the allocation policy chooses the first name ℎ in that enumeration satisfying ℎ∉fv(𝑅′⟨𝑒′⟩)∪fn(𝑅′⟨𝑒′⟩)∪dom(𝜌′)∪⋃𝑞∈rng(𝜌′)fn(𝑞)∪⋃𝑣∈rng(𝐺′)fn(𝑣). Every entry of the finite map 𝜌 has the form ℎ↦𝜆⃗𝑥.𝑄, where ⃗𝑥 is the ordered vector fv(𝑄), and every such abstraction is closed. The selector used by A4a is a fixed deterministic selector from the finite set of strict proper subexpressions 𝑒1 satisfying 𝑒1≼̂𝑔 and ̂𝑔⧸≼𝑒1. The functions 𝗌𝗍𝗋𝗂𝖼𝗍, 𝗅𝗂𝗇𝖾𝖺𝗋, 𝗆𝗌𝗀, and 𝗌𝗉𝗅𝗂𝗍 are exactly the finite syntax-directed functions displayed in this chapter.
Proof of Lemma 128.12 — Ledger totality and functionality
Proof. Inspect the outer form of the focus. Numerals, variables, globals, constructors, lambdas, primitives, applications, lets, letrecs, and cases are the disjoint outer forms in definition 128.1. Within one outer form, the side conditions printed in the ordered ledger are tested in order; the final arm of R8, the second arm of R13, and R20 cover failure of all earlier tests. A reachable global has exactly one value in 𝐺 by admissibility. For its application ledger, A1–A3 are tested in order; if none applies, the deterministic finite selector decides A4a, and the decidable occurrence test then distinguishes A4b from A4c. Thus at least one clause applies. Ordered selection prevents two clauses from being selected. ◻
For an admissible initial state, there is a lexicographic measure 𝑊:reachabledriverstates→ℕ4 such that every recursive driver call on the right side of a selected R1–R20 or A1–A4c clause has smaller measure than its parent.
Proof of Lemma 128.13 — Strict descent of recursive driver calls
Proof. Fix the admissible initial state S0=𝖣𝑅0,𝐺0,𝜌0(𝑒0). Consider the tree of memo-table extensions reachable from S0 without an earlier memoized configuration embedding a later one. It is finitely branching: a term has finitely many subterms and branches, the signatures are finite, and the A4a selector is fixed. It has no infinite branch by theorem 128.4. König’s lemma therefore makes this tree finite. For completeness, if it were infinite, its finite root degree would leave one child with infinitely many descendants; repeating that choice would construct an infinite branch. Let 𝑁(S0) be the finite tree’s maximum extension depth.
For a reachable state S=𝖣𝑅,𝐺,𝜌(𝑒), put 𝑑S0(𝜌)=|dom(𝜌)∖dom(𝜌0)|. Define 𝑊S0(S)=(𝑁(S0)−𝑑S0(𝜌),𝜅(𝑅⟨𝑒⟩),𝗐𝗍(𝑅⟨𝑒⟩),𝗐𝗍(𝑒)). Reachability gives 𝑑S0(𝜌)≤𝑁(S0), so this is a quadruple of natural numbers.
We verify the rule families. Rules R1–R3 and R20 either stop or delegate to the application ledger. Rules R4–R6 recurse on proper subterms. Their case count cannot increase, and their plugged weight decreases when the case counts agree. Rule R7 replaces a primitive node by its weight-two numeral result. In the first arm of R8, both operands are proper subterms; in its other arms the plugged configuration is unchanged and the focused weight decreases. Rule R9 removes one application-or-lambda node when it changes beta application into the single vector-let former. Rule R10 preserves the plugged application and focuses on its proper head. Rules R11 and R12 replace a weight-two bound-variable occurrence by a weight-two numeral or source variable and remove the positive weight of the let and its right-hand side. In the substitution arm of R13, strictness supplies at least one occurrence of 𝑥 and linearity supplies at most one. There is therefore exactly one occurrence: substitution adds one copy of 𝑒, removes the weight-two occurrence of 𝑥, and removes the let former and its separate right-hand side. In the other arm, each of the two recursive calls is on a proper component. Rule R14 removes the letrec former and its stored value from the driven term.
Rules R15–R17 remove the selected case node. Pattern substitution can duplicate constructor syntax but cannot introduce a case node, so the second component strictly decreases. In R18, every recursive input is a proper scrutinee or branch component of the selected case; its case count is strictly smaller than that of the whole case. Rule R19 preserves the plugged case, its case count, and its plugged weight, but decreases the focused fourth component.
Alternatives A1 and A2 make no recursive call. In A3, unequal-head splitting returns proper spine components; equal-head generalization returns a common spine and disagreement ranges that are proper parts of the selected configuration. Alternative A2 has already rejected mutual embedding, so at least one disagreement is strict. The size induction and split-weight assertion in lemma 128.5 therefore decrease the case-count–weight pair for every A3 recursive call: splitting introduces no case node, and its weight strictly decreases when the case count is unchanged.
The common first step of A4a–A4c extends 𝜌 to 𝜌′ before driving the unfolded body. Its recursive call therefore decreases the first component regardless of the body’s size. If A4a is then selected, its term 𝑒1 is a strict syntactic subterm of that driven body and the progress guard makes 𝑒1≼̂𝑔 strict. The split-weight assertion of lemma 128.5 therefore makes every additional A4a call smaller in the case-count–weight pair. Alternatives A4b and A4c make no further recursive call. These are all ordered clauses, and lexicographic order on ℕ4 is well founded. ◻
Let 𝖣𝑅,𝐺,𝜌(𝑒) be an admissible initial driver state such that (fv(𝑅⟨𝑒⟩)∪fn(𝑅⟨𝑒⟩))∩dom(𝜌)=∅. Its strictness-guided driving, variant folding, embedding whistle, split and generalization policy, and residualization terminate. Put 𝑒′=𝜌(𝖣𝑅,𝐺,𝜌(𝑒)). Then 𝑅⟨𝑒⟩⪯𝗌𝑒′. Consequently, for every 𝐻 with closes(𝐻;𝑅⟨𝑒⟩,𝑒′), (∃𝑘,𝑣.𝐻⟨𝑅⟨𝑒⟩⟩⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣)⟺(∃𝑘′,𝑣′.𝐻⟨𝑒′⟩⇓𝑘′𝖼𝖺𝗅𝗅𝗌𝑣′). Moreover, for every such 𝐻, every 𝑘∈ℕ, and every closed value 𝑣, 𝐻⟨𝑅⟨𝑒⟩⟩⇓𝑘𝖼𝖺𝗅𝗅𝗌𝑣⟹∃𝑘′≤𝑘,𝑣′.𝐻⟨𝑒′⟩⇓𝑘′𝖼𝖺𝗅𝗅𝗌𝑣′.
Proof of Theorem 128.14 — SC-CBV termination and correctness
Proof. By lemma 128.12, exactly one ledger clause is selected at each reachable state. Well-founded induction on the measure of lemma 128.13 proves termination: that clause performs finite local work, and every recursive premise has smaller measure.
Use the same induction for correctness and apply lemma 128.10 at its final step. Each recursive call uses its actual (𝑅𝑗,𝐺𝑗,𝜌𝑗); in particular, the A4b premise uses the extended allocation map 𝜌′, while the clause lemma transports its conclusion back to the outer 𝜌. A variant back edge emits the allocated name and invokes no recursive driver call. Every other clause receives its hypotheses from strict descendants. The clause conclusion at the root is 𝑅⟨𝑒⟩⪯𝗌𝜌(𝖣𝑅,𝐺,𝜌(𝑒)). Unfolding the three conjuncts of strong improvement gives termination in both directions and the stated bound on named calls. No claim is made for a different evaluator, split policy, or effectful language. ◻
The disjointness hypothesis cannot be removed. Let ℎ be an ordinary free variable, take 𝑅=[] and 𝑒=ℎ0, and let 𝜌 contain the residual name ℎ with closed function 𝜆𝑥.0. Rule R5 leaves the head variable in place, so closing the residual changes ℎ0 to (𝜆𝑥.0)0. Let Ω be a closed divergent term, and close the source occurrence of ℎ with 𝜆𝑥.1 in the observation context 𝐻=(𝜆ℎ.𝖼𝖺𝗌𝖾[]𝗈𝖿{0⇒Ω;1⇒0})(𝜆𝑥.1). Then 𝐻⟨ℎ0⟩ terminates, whereas 𝐻⟨(𝜆𝑥.0)0⟩ diverges. Thus the source configuration does not operationally approximate the residual term.
Under the hypotheses of theorem 128.14, every residual function abstracts exactly the free variables of its memoized configuration, every fold supplies those variables in that order, and the final residual expression has no free variable outside fv(𝑅⟨𝑒⟩).
Proof of Proposition 128.16 — Residual well-scopedness
Proof. Maintain the invariant that a call 𝖣𝑅,𝐺,𝜌(𝑒) may emit only variables free in 𝑅⟨𝑒⟩, variables in the ordered parameter lists of entries in 𝜌, and variables bound by the residual syntax surrounding that call. Rules R1–R12 and R20 preserve this set by plugging, congruence, or capture-avoiding substitution. In R13, alpha-renaming the let binder apart makes the substitution arm capture avoiding; the other arm binds 𝑥 around both residual subterms. Rule R14 alpha-renames 𝑔 and the parameters of its value apart before extending 𝐺, so expansion introduces no free occurrence of either binder. Rules R15–R19 bind every pattern field in its branch and apply the edge substitution to the branch body and recorded context.
For A1, the renaming 𝜎 is applied to the ordered list fv(𝑒1), so the fold supplies exactly the parameters of the selected memo entry. Rule A2 introduces no name. In A3 and A4a, the split side condition places ⃗𝑦 outside the free variables of both inputs; alpha-renaming places the surrounding binders outside ⃗𝑦. Moreover, 𝑓𝑔[⃗𝑓/⃗𝑦]=̂𝑔; substituting the driven witnesses therefore removes every introduced 𝑦𝑖. In A4b, the name ℎ satisfies the allocation condition. The recursive binding binds ℎ, and its lambda binds the ordered vector ⃗𝑥=fv(̂𝑔); every recursive occurrence uses that vector. Rule A4c requires ℎ∉fn(𝑒), so discarding the allocation leaves no free ℎ. These are all ledger clauses. At the root there is no surrounding residual binder, and applying 𝜌 closes every allocated name. The remaining free variables are therefore contained in fv(𝑅⟨𝑒⟩), as claimed. ◻
The fusion calculation starts from the configuration 𝑄0(𝑥𝑠,𝑦𝑠)=𝖺𝗉𝗉𝖾𝗇𝖽(𝗆𝖺𝗉(𝑓,𝑥𝑠),𝗆𝖺𝗉(𝑓,𝑦𝑠)). Driving the case on 𝑥𝑠 gives 𝑄0(𝖭𝗂𝗅,𝑦𝑠)=𝗆𝖺𝗉(𝑓,𝑦𝑠),𝑄0(𝖢𝗈𝗇𝗌(𝑎,𝑎𝑠),𝑦𝑠)=𝖢𝗈𝗇𝗌(𝑓(𝑎),𝑄0(𝑎𝑠,𝑦𝑠)). The nil branch opens a case on 𝑦𝑠. Its cons successor is a variant of 𝑄0(𝖭𝗂𝗅,𝑏𝑠), so folding closes the graph. With residual name ℎ, the complete residual equation is ℎ(𝑥𝑠,𝑦𝑠)=𝖼𝖺𝗌𝖾𝑥𝑠𝗈𝖿𝖭𝗂𝗅⇒𝖼𝖺𝗌𝖾𝑦𝑠𝗈𝖿{𝖭𝗂𝗅⇒𝖭𝗂𝗅,𝖢𝗈𝗇𝗌(𝑏,𝑏𝑠)⇒𝖢𝗈𝗇𝗌(𝑓(𝑏),ℎ(𝖭𝗂𝗅,𝑏𝑠)),𝖢𝗈𝗇𝗌(𝑎,𝑎𝑠)⇒𝖢𝗈𝗇𝗌(𝑓(𝑎),ℎ(𝑎𝑠,𝑦𝑠)). Neither 𝗆𝖺𝗉 nor 𝖺𝗉𝗉𝖾𝗇𝖽 occurs in this residual program, and each input constructor is inspected once. The fuelled specializer of chapter 127 retains the producer–consumer boundary when both lists are unknown. This comparison concerns these systems and inputs, not a universal ordering.
Sources and seminar
The SC-CBV rule card and examples follow the extended proof report and the later strict-subexpression presentation, except that A4a carries the progress guard stated and justified beside the rule. The printed later rule requires only a strict proper subexpression 𝑒1 with 𝑒1≼̂𝑔; the variable-sharing example beside the local rule shows why that premise does not establish strict weight descent. The thesis supplies additional examples [Jó08, JN10, JN08]. The only imported proof in this chapter is Kruskal’s tree theorem, at the exact source location recorded in theorem 128.4; the driver descent, strong-improvement algebra, recursive replacement, clause adequacy, and total correctness arguments are proved locally. Turchin’s system, normal-order positive supercompilation, call-by-need variants, and distillation have different observations or control policies and lend no unstated theorem to theorem 128.14.
Suggested first pass.
None of these problems is a prerequisite for a later chapter. Begin with exercise 128.3, then complete exercise 128.5.
★★☆ Build the first five nodes for 𝗅𝗈𝗈𝗉(𝑥)=𝗅𝗈𝗈𝗉(𝗌𝗎𝖼(𝑥)). Mark the first embedding pair, compute its most-specific generalization, and prove both equations.
★★★ Design a folding test that ignores constructor heads. Give a closed input on which it changes the returned constructor. Repair the test with variant equivalence and prove the repaired back-edge equation.
★★★Practical project.sc-cbv-whistle-visualizer Implement the finite Kappa constructor-tree model from the tutorial. Emit deterministic fold, whistle, and drive decisions. Maintain the invariant that variant equality is tested before embedding and that every returned generalization witness reconstructs both input trees. Replay the ordered rules R1–R20 and alternatives A1–A4c. The named cases print these exact lines: 𝚟𝚊𝚛𝚒𝚊𝚗𝚝:𝚏𝚘𝚕𝚍𝚐𝚛𝚘𝚠𝚝𝚑:𝚠𝚑𝚒𝚜𝚝𝚕𝚎𝚞𝚗𝚛𝚎𝚕𝚊𝚝𝚎𝚍:𝚍𝚛𝚒𝚟𝚎𝚖𝚜𝚐-𝚠𝚒𝚝𝚗𝚎𝚜𝚜:𝚟𝚊𝚕𝚒𝚍. Change the folding test to ignore constructor heads. Replay the named cases, and explain which premise of theorem 128.14 it violates. The finite model does not certify the full SC-CBV transformer.