Gabriel Kerneis

Juliusz Chroboczek

Lambda-lifting and CPS conversion in an imperative language

companion technical report to the article "Continuation-Passing C: from threads to events through continuations". It contains the complete version of the proofs of correctness of lambda-lifting and CPS-conversion presented in the article.

Introduction

This paper is a companion technical report to the article "Continuation-Passing C: from threads to events through continuations" [START_REF] Kerneis | Continuation-Passing C: from threads to events through continuations[END_REF]. It contains the complete version of the proofs presented in the article. It does not, however, give any background or motivation for our work: please refer to the original article.

Lambda-lifting in an imperative language

To prove the correctness of lambda-lifting in an imperative, call-by-value language when functions are called in tail position, we do not reason directly on CPC programs, because the semantics of C is too broad and complex for our purposes. The CPC translator leaves most parts of converted programs intact, transforming only control structures and function calls. Therefore, we define a simple language with restricted values, expressions and terms, that captures the features we are most interested in (Section 2.1).

The reduction rules for this language (Section 2.1.1) use a simplified memory model without pointers and enforce that local variables are not accessed outside of their scope, as ensured by our boxing pass. This is necessary since lambda-lifting is not correct in general in the presence of extruded variables.

It turns out that the "naive" reduction rules defined in Section 2.1.1 do not provide strong enough invariants to prove this correctness theorem by induction, mostly because we represent memory with a store that is not invariant with respect to lambda-lifting. Therefore, in Section 2.2, we define an equivalent, "optimised" set of reduction rules which enforces more regular stores and closures.

The proof of correctness is then carried out in Section 2.4 using these optimised rules. We first define the invariants needed for the proof and formulate a strengthened version of the correctness theorem (Theorem 2.28, Section 2.4.1). A comprehensive overview of the proof is then given in Section 2.4.2. The proof is fully detailed in Section 2.4.5, with the help of a number of lemmas to keep the main proof shorter (Sections 2.4.3 and 2.4.4).

The main limitation of this proof is that Theorems 2.9 and 2.28 are implications, not equivalences: we do not prove that if a term does not reduce, it will not reduce once lifted. For instance, this proof does not ensure that lambda-lifting does not break infinite loops.

Definitions

In this section, we define the terms (Definition 2.1), the reduction rules (Section 2.1.1) and the lambda-lifting transformation itself (Section 2.1.2) for our small imperative language. With these preliminary definitions, we are then able to characterise liftable parameters (Definition 2.8) and state the main correctness theorem (Theorem 2.9, Section 2.1.3). Our language focuses on the essential details affected by the transformations: recursive functions, conditionals and memory accesses. Loops, for instance, are ignored because they can be expressed in terms of recursive calls and conditional jumps -and that is, in fact, how the splitting pass translates them. Since lambda-lifting happens after the splitting pass, our language need to include inner functions (although they are not part of the C language), but it can safely exclude goto statements.

Naive reduction rules

Environments and stores Handling inner functions requires explicit closures in the reduction rules. We need environments, written ρ, to bind variables to locations, and a store, written s, to bind locations to values.

Environments and stores are partial functions, equipped with a single operator which extends and modifies a partial function:

• + {• → •}.
Definition 2.2. The modification (or extension) f ′ of a partial function f , written f ′ = f +{x → y}, is defined as follows: Note that although we have a notion of locations, which correspond roughly to memory addresses in C, there is no way to copy, change or otherwise manipulate a location directly in the syntax of our language. This is on purpose, since adding this possibility would make lambdalifting incorrect: it translates the fact, ensured by the boxing pass in the CPC translator, that there are no extruded variables in the lifted terms.

f ′ (t) = y when t = x f (t) otherwise dom(f ′ ) = dom(f ) ∪ {x}
Reduction rules We use classical big-step reduction rules for our language (Figure 1, p. 4).

In the (call) rule, we need to introduce fresh locations for the parameters of the called function. This means that we must choose locations that are not already in use, in particular in the environments ρ ′ and F . To express this choice, we define two ancillary functions, Env and Loc, to extract the environments and locations contained in the closures of a given environment of functions F . (assign)

a s ρ ---→ F v s ′ ρ x = l ∈ dom s ′ x := a s ρ ---→ F 1 s ′ +{l →v} (seq) a s ρ ---→ F v s ′ b s ′ ρ ---→ F v ′ s ′′ a ; b s ρ ---→ F v ′ s ′′ (if-t.) a s ρ ---→ F true s ′ b s ′ ρ ---→ F v s ′′ if a then b else c s ρ ---→ F v s ′′ (if-f.) a s ρ ---→ F false s ′ c s ′ ρ ---→ F v s ′′ if a then b else c s ρ ---→ F v s ′′ (letrec) b s ρ ----→ F ′ v s ′ F ′ = F + {f → [λx 1 . . . x n .a, ρ, F ]} letrec f (x 1 . . . x n ) = a in b s ρ ---→ F v s ′ (call) F f = [λx 1 . . . x n .b, ρ ′ , F ′ ] ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n ) l i fresh and distinct ∀i, a si i ρ ---→ F v si+1 i b sn+1+{li →vi} ρ ′′ •ρ ′ -----------→ F ′ +{f →F f } v s ′ f (a 1 . . . a n ) s1 ρ ---→ F v s ′
Env(F ) = {ρ, ρ ′ | [λx 1 . . . x n .M, ρ, F ′ ] ∈ Im(F ), ρ ′ ∈ Env(F ′ )} Loc(F ) = {Im(ρ) | ρ ∈ Env(F )}
A location l is said to appear in F iff l ∈ Loc(F ).

These functions allow us to define fresh locations.

Definition 2.5 (Fresh location). In the (call) rule, a location is fresh when: -l / ∈ dom(s n+1 ), i.e. l is not already used in the store before the body of f is evaluated, and -l doesn't appear in F ′ + {f → F f }, i.e. l will not interfere with locations captured in the environment of functions.

Note that the second condition implies in particular that l does not appear in either F or ρ ′ .

Lambda-lifting

Lambda-lifting can be split into two parts: parameter lifting and block floating [START_REF] Danvy | Lambda-lifting in quadratic time[END_REF]. We will focus only on the first part here, since the second one is trivial. Parameter lifting consists in adding a free variable as a parameter of every inner function where it appears free. This step is repeated until every variable is bound in every function, and closed functions can safely be floated to top-level. Note that although the transformation is called lambda-lifting, we do not focus on a single function and try to lift all of its free variables; on the contrary, we define the lifting of a single free parameter x in every possible function.

Smart lambda-lifting algorithms strive to minimize the number of lifted variables. Such is not our concern in this proof: parameters are lifted in every function where they might potentially be free. Definition 2.6 (Parameter lifting in a term). Assume that x is defined as a parameter of a given function g, and that every inner function in g is called h i (for some i ∈ N). Also assume that function parameters are unique before lambda-lifting. Then the lifted form (M ) * of the term M with respect to x is defined inductively as follows:

(1) * = 1 (n) * = n (true) * = true (f alse) * = f alse (y) * = y and (y := a) * = y := (a) * (even if y = x) (a ; b) * = (a) * ; (b) * (if a then b else c) * = if (a) * then (b) * else (c) * (letrec f (x 1 . . . x n ) = a in b) * = letrec f (x 1 . . . x n x) = (a) * in (b) * if f = h i letrec f (x 1 . . . x n ) = (a) * in (b) * otherwise (f (a 1 . . . a n )) * = f ((a 1 ) * , . . . , (a n ) * , x) if f = h i for some i f ((a 1 ) * , . . . , (a n ) * ) otherwise 2.

Correctness condition

We show that parameter lifting is correct for variables defined in functions whose inner functions are called exclusively in tail position. We call these variables liftable parameters.

We first define tail positions as usual [START_REF] William | Proper tail recursion and space efficiency[END_REF]:

Definition 2.7 (Tail position). Tail positions are defined inductively as follows:

1. M and N are in tail position in if P then M else N . 2. N is in tail position in N and M ; N and letrec f (x 1 . . . x n ) = M in N .

A parameter x defined in a function g is liftable if every inner function in g is called exclusively in tail position. Definition 2.8 (Liftable parameter). A parameter x is liftable in M when:

-x is defined as the parameter of a function g, -inner functions in g, named h i , are called exclusively in tail position in g or in one of the h i .

Our main theorem states that performing parameter-lifting on a liftable parameter preserves the reduction:

Theorem 2.9 (Correctness of lambda-lifting). If x is a liftable parameter in M , then ∃t, M ε ε ---→ ε v t implies ∃t ′ , (M ) ε * ε ---→ ε v t ′ .
Note that the resulting store t ′ changes because lambda-lifting introduces new variables, hence new locations in the store, and changes the values associated with lifted variables; Section 2.4 is devoted to the proof of this theorem. To maintain invariants during the proof, we need to use an equivalent, "optimised" set of reduction rules; it is introduced in the next section.

Optimised reduction rules

The naive reduction rules (Section 2.1.1) are not well-suited to prove the correctness of lambdalifting. Indeed, the proof is by induction and requires a number of invariants on the structure of stores and environments. Rather than having a dozen of lemmas to ensure these invariants during the proof of correctness, we translate them as constraints in the reduction rules.

To this end, we introduce two optimisations -minimal stores (Section 2.2.1) and compact closures (Section 2.2.2) -which lead to the definition of an optimised set of reduction rules (Figure 2, Section 2.2.3). The equivalence between optimised and naive reduction rules is shown in Section 2.3.

Minimal stores

In the naive reduction rules, the store grows faster when reducing lifted terms, because each function call adds to the store as many locations as it has function parameters. This yields stores of different sizes when reducing the original and the lifted term, and that difference cannot be accounted for locally, at the rule level.

Consider for instance the simplest possible case of lambda-lifting:

letrec g(x) = (letrec h() = x in h()) in g(1) (original) letrec g(x) = (letrec h(y) = y in h(x)) in g(1) (lifted)
At the end of the reduction, the store for the original term is {l x → 1} whereas the store for the lifted term is {l x → 1; l y → 1}. More complex terms would yield even larger stores, with many out-of-date copies of lifted variables.

To keep the store under control, we need to get rid of useless variables as soon as possible during the reduction. It is safe to remove a variable x from the store once we are certain that it will never be used again, i.e. as soon as the term in tail position in the function which defines x has been evaluated. This mechanism is analogous to the deallocation of a stack frame when a function returns.

To track the variables whose location can be safely reclaimed after the reduction of some term M , we introduce split environments. Split environments are written ρ T |ρ, where ρ T is called the tail environment and ρ the non-tail one; only the variables belonging to the tail environment may be safely reclaimed. The reduction rules build environments so that a variable x belongs to ρ T if and only if the term M is in tail position in the current function f and x is a parameter of f . In that case, it is safe to discard the locations associated to all of the parameters of f , including x, after M has been reduced because we are sure that the evaluation of f is completed (and there are no first-class functions in the language to keep references on variables beyond their scope of definition).

We also define a cleaning operator, • \ •, to remove a set of variables from the store.

Definition 2.10 (Cleaning of a store). The store s cleaned with respect to the variables in ρ, written s \ ρ, is defined as s \ ρ = s| dom(s)\Im(ρ) .

Compact closures

Another source of complexity with the naive reduction rules is the inclusion of useless variables in closures. It is safe to remove from the environments of variables contained in closures the variables that are also parameters of the function: when the function is called, and the environment restored, these variables will be hidden by the freshly instantiated parameters.

This is typically what happens to lifted parameters: they are free variables, captured in the closure when the function is defined, but these captured values will never be used since calling the function adds fresh parameters with the same names. We introduce compact closures in the optimised reduction rules to avoid dealing with this hiding mechanism in the proof of lambda-lifting.

A compact closure is a closure that does not capture any variable which would be hidden when the closure is called because of function parameters having the same name.

. . . x n .M, ρ, F ] is compact if ∀i, x i /
∈ dom(ρ) and F is compact. An environment is compact if it contains only compact closures.

We define a canonical mapping from any environment F to a compact environment F * , restricting the domains of every closure in F . Definition 2.12 (Canonical compact environment). The canonical compact environment F * is the unique environment with the same domain as F such that

∀f ∈ dom(F ), F f = [λx 1 . . . x n .M, ρ, F ′ ] implies F * f = λx 1 . . . x n .M, ρ| dom(ρ)\{x1...xn} , F ′ * .

Optimised reduction rules

Combining both optimisations yields the optimised reduction rules (Figure 2, p. 8), used Section 2.4 for the proof of lambda-lifting. We ensure minimal stores by cleaning them in the (val), (var) and (assign) rules, which correspond to tail positions; split environments are introduced in the (call) rule to distinguish fresh parameters, to be cleaned, from captured variables, which are preserved. Tail positions are tracked in every rule through split environments, to avoid cleaning variables too early, in a non-tail branch. We also build compact closures in the (letrec) rule by removing the parameters of f from the captured environment ρ ′ . Theorem 2.13 (Equivalence between naive and optimised reduction rules). Optimised and naive reduction rules are equivalent: every reduction in one set of rules yields the same result in the other. It is necessary, however, to take care of locations left in the store by the naive reduction:

M ε ε|ε = === ⇒ ε v ε iff ∃s, M ε ε ---→ ε v s
We prove this theorem in Section 2.3.

Equivalence of optimised and naive reduction rules

This section is devoted to the proof of equivalence between the optimised naive reduction rules (Theorem 2.13).

To clarify the proof, we introduce intermediate reduction rules (Figure 3, p. 9), with only one of the two optimisations: minimal stores, but not compact closures.

The

v s ρT |ρ = ==== ⇒ F v s\ρT (var) ρ T • ρ x = l ∈ dom s x s ρT |ρ = ==== ⇒ F s l s\ρT (assign) a s |ρT •ρ =====⇒ F v s ′ ρ T • ρ x = l ∈ dom s ′ x := a s ρT |ρ = ==== ⇒ F 1 s ′ +{l →v}\ρT (seq) a s |ρT •ρ =====⇒ F v s ′ b s ′ ρT |ρ = ==== ⇒ F v ′ s ′′ a ; b s ρT |ρ = ==== ⇒ F v ′ s ′′ (if-t.) a s |ρT •ρ =====⇒ F true s ′ b s ′ ρT |ρ = ==== ⇒ F v s ′′ if a then b else c s ρT |ρ = ==== ⇒ F v s ′′ (if-f.) a s |ρT •ρ =====⇒ F false s ′ c s ′ ρT |ρ = ==== ⇒ F v s ′′ if a then b else c s ρT |ρ = ==== ⇒ F v s ′′ (letrec) b s ρT |ρ = ==== ⇒ F ′ v s ′ ρ ′ = ρ T • ρ| dom(ρT •ρ)\{x1...xn} F ′ = F + {f → [λx 1 . . . x n .a, ρ ′ , F ]} letrec f (x 1 . . . x n ) = a in b s ρT |ρ = ==== ⇒ F v s ′ (call) F f = [λx 1 . . . x n .b, ρ ′ , F ′ ] ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n ) l i fresh and distinct ∀i, a si i |ρT •ρ =====⇒ F v si+1 i b sn+1+{li →vi} ρ ′′ |ρ ′ = ========== ⇒ F ′ +{f →F f } v s ′ f (a 1 . . . a n ) s1 ρT |ρ = ==== ⇒ F v s ′ \ρT

Optimised rules

We must therefore show that it is correct to use compact closures in the optimised reduction rules.

Compact closures carry the implicit idea that some variables can be safely discarded from the environments when we know for sure that they will be hidden. The following lemma formalises this intuition. Lemma 2.14 (Hidden variables elimination).

∀l, l ′ , M s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v s ′ iff M s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v s ′ ∀l, l ′ , M s ρT •(x,l)|ρ = ======= ⇒ F v s ′ iff M s ρT •(x,l)|(x,l ′ )•ρ = =========== ⇒ F v s ′
Moreover, both derivations have the same height.

Proof. The exact same proof holds for both intermediate and optimised reduction rules. By induction on the structure of the derivation. The proof relies solely on the fact that

ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ. (val) v s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s\ρT (var) ρ T • ρ x = l ∈ dom s x s ρT |ρ ≡ ≡≡≡≡ ⇛ F s l s\ρT (assign) a s |ρT •ρ ≡≡≡≡≡⇛ F v s ′ ρ T • ρ x = l ∈ dom s ′ x := a s ρT |ρ ≡ ≡≡≡≡ ⇛ F 1 s ′ +{l →v}\ρT (seq) a s |ρT •ρ ≡≡≡≡≡⇛ F v s ′ b s ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ s ′′ a ; b s ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ s ′′ (if-t.) a s |ρT •ρ ≡≡≡≡≡⇛ F true s ′ b s ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′′ if a then b else c s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′′ (if-f.) a s |ρT •ρ ≡≡≡≡≡⇛ F false s ′ c s ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′′ if a then b else c s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′′ (letrec) b s ρT |ρ ≡ ≡≡≡≡ ⇛ F ′ v s ′ ρ ′ = ρ T • ρ F ′ = F + {f → [λx 1 . . . x n .a, ρ, F ]} letrec f (x 1 . . . x n ) = a in b s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ (call) F f = [λx 1 . . . x n .b, ρ ′ , F ′ ] ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n ) l i fresh and distinct ∀i, a si i |ρT •ρ ≡≡≡≡≡⇛ F v si+1 i b sn+1+{li →vi} ρ ′′ |ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′ f (a 1 . . . a n ) s1 ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ \ρT
(seq) ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ. So, a s |ρT •(x,l)•(x,l ′ )•ρ ≡≡≡≡≡≡≡≡≡≡≡≡⇛ F v s ′ iff a s |ρT •(x,l)•ρ ≡ ≡≡≡≡≡≡≡≡ ⇛ F v s ′
Moreover, by the induction hypotheses,

b s ′ ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v ′ s ′′ iff b s ′ ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v ′ s ′′ Hence, a ; b s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v ′ s ′′ iff a ; b s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v ′ s ′′
The other cases are similar.

(val) v s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v s\ρT •(x,l) iff v s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v s\ρT •(x,l) (var) ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ so, with l ′′ = ρ T • (x, l) • ρ y, y s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F s l ′′ s\ρT •(x,l) iff y s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F s l ′′ s\ρT •(x,l) (assign) ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ. So, a s |ρT •(x,l)•(x,l ′ )•ρ ≡≡≡≡≡≡≡≡≡≡≡≡⇛ F v s ′ iff a s |ρT •(x,l)•ρ ≡ ≡≡≡≡≡≡≡≡ ⇛ F v s ′ Hence, with l ′′ = ρ T • (x, l) • ρ y, y := a s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F 1 s ′ +{l ′′ →v}\ρT •(x,l) iff y := a s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F 1 s ′ +{l ′′ →v}\ρT •(x,l)
(if-true) and (if-false) are proved similarly to (seq).

(letrec) ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ = ρ ′ . Moreover, by the induction hypotheses, b s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ v s ′ iff b s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F ′ v s ′ Hence, letrec f (x 1 . . . x n ) = a in b s ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v s ′ iff letrec f (x 1 . . . x n ) = a in b s ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v s ′ (call) ρ T • (x, l) • ρ = ρ T • (x, l) • (x, l ′ ) • ρ. So, ∀i, a si i |ρT •(x,l)•(x,l ′ )•ρ ≡≡≡≡≡≡≡≡≡≡≡≡⇛ F v si+1 i iff a si i |ρT •(x,l)•ρ ≡ ≡≡≡≡≡≡≡≡ ⇛ F v si+1 i
Hence,

f (a 1 . . . a n ) s1 ρT •(x,l)|(x,l ′ )•ρ ≡ ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F v s ′ \ρT •(x,l) iff f (a 1 . . . a n ) s1 ρT •(x,l)|ρ ≡ ≡≡≡≡≡≡≡ ⇛ F v s ′ \ρT •(x,l) .
Now we can show the required lemmas and prove the equivalence between the intermediate and optimised reduction rules.

Lemma 2.15 (Intermediate implies optimised).

If M s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ then M s ρT |ρ = ==== ⇒ F * v s ′ .
Proof. By induction on the structure of the derivation. The interesting cases are (letrec) and (call), where compact environments are respectively built and used.

(letrec) By the induction hypotheses,

b s ρT |ρ = ==== ⇒ F ′ * v s ′
Since we defined canonical compact environments so as to match exactly the way compact environments are built in the optimised reduction rules, the constraints of the (letrec) rule are fulfilled:

F ′ * = F * + {f → [λx 1 . . . x n .a, ρ ′ , F * ]}, hence: letrec f (x 1 . . . x n ) = a in b s ρT |ρ = ==== ⇒ F * v s ′ (call) By the induction hypotheses, ∀i, a si i |ρT •ρ =====⇒ F * v si+1 i and b sn+1+{li →vi} ρ ′′ |ρ ′ = ============ ⇒ (F ′ +{f →F f }) * v s ′
Lemma 2.14 allows to remove hidden variables, which leads to

b sn+1+{li →vi} ρ ′′ |ρ ′ | dom(ρ ′ )\{x 1 ...xn } = =============== ⇒ (F ′ +{f →F f }) * v s ′ Besides, F * f = λx 1 . . . x n .b, ρ ′ | dom(ρ ′ )\{x1...xn} , F ′ * and (F ′ + {f → F f }) * = F ′ * + {f → F * f } Hence f (a 1 . . . a n ) s1 ρT |ρ = ==== ⇒ F * v s ′ \ρT . (val) v s ρT |ρ = ==== ⇒ F * v s\ρT (var) x s ρT |ρ = ==== ⇒ F * s l s\ρT (assign) By the induction hypotheses, a s |ρT •ρ =====⇒ F * v s ′ . Hence, x := a s ρT |ρ = ==== ⇒ F * 1 s ′ +{l →v}\ρT
(seq) By the induction hypotheses,

a s |ρT •ρ =====⇒ F * v s ′ b s ′ ρT |ρ = ==== ⇒ F * v ′ s ′′ Hence, a ; b s ρT |ρ = ==== ⇒ F * v ′ s ′′
(if-true) and (if-false) are proved similarly to (seq).

Lemma 2.16 (Optimised implies intermediate).

If M s ρT |ρ = ==== ⇒ F v s ′ then ∀G such that G * = F , M s ρT |ρ ≡ ≡≡≡≡ ⇛ G v s ′ .
Proof. First note that, since G * = F , F is necessarily compact. By induction on the structure of the derivation. The interesting cases are (letrec) and (call), where non-compact environments are respectively built and used.

(letrec) Let G such as G * = F . Remember that ρ ′ = ρ T • ρ| dom(ρT •ρ)\{x1...xn} . Let G ′ = G + {f → [λx 1 . . . x n .a, ρ T • ρ, F ]} which leads, since F is compact (F * = F ), to G ′ * = F + {f → [λx 1 . . . x n .a, ρ ′ , F ]} = F ′ By the induction hypotheses, b s ρT |ρ ≡ ≡≡≡≡ ⇛ G ′ v s ′ Hence, letrec f (x 1 . . . x n ) = a in b s ρT |ρ ≡ ≡≡≡≡ ⇛ G v s ′ (call) Let G such as G * = F . By the induction hypotheses, ∀i, a si i |ρT •ρ ≡≡≡≡≡⇛ G v si+1 i Moreover, since G * f = F f , G f = [λx 1 . . . x n .b, (x i , l i ) • . . . • (x j , l j )ρ ′ , G ′ ]
where G ′ * = F ′ , and the l i are some locations stripped out when compacting G to get F . By the induction hypotheses,

b sn+1+{li →vi} ρ ′′ |ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ G ′ +{f →G f } v s ′ Lemma 2.14 leads to b sn+1+{li →vi} ρ ′′ |(xi,li)•...•(xj,lj )ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ ⇛ G ′ +{f →G f } v s ′ Hence, f (a 1 . . . a n ) s1 ρT |ρ ≡ ≡≡≡≡ ⇛ G v s ′ \ρT . (val) ∀G such as G * = F , v s ρT |ρ ≡ ≡≡≡≡ ⇛ G v s ′ (var) ∀G such as G * = F , x s ρT |ρ ≡ ≡≡≡≡ ⇛ G s l s\ρT (assign) Let G such as G * = F . By the induction hypotheses, a s |ρT •ρ ≡≡≡≡≡⇛ G v s ′ . Hence, x := a s ρT |ρ ≡ ≡≡≡≡ ⇛ G 1 s ′ +{l →v}\ρT (seq) Let G such as G * = F . By the induction hypotheses, a s |ρT •ρ ≡≡≡≡≡⇛ G v s ′ b s ′ ρT |ρ ≡ ≡≡≡≡ ⇛ G v ′ s ′′ Hence a ; b s ρT |ρ ≡ ≡≡≡≡ ⇛ G v ′ s ′′
(if-true) and (if-false) are proved similarly to (seq).

Intermediate and naive reduction rules equivalence

In this section, we show that the naive and intermediate reduction rules are equivalent:

Naive rules

Lemma 2.22 -========= - Lemma 2.21

Intermediate rules

We must therefore show that it is correct to use minimal stores in the intermediate reduction rules. We first define a partial order on stores:

Definition 2.17 (Store extension).

s ⊑ s ′ iff s ′ | dom(s) = s
Property 2.18. Store extension (⊑) is a partial order over stores. The following operations preserve this order: • \ ρ and • + {l → v}, for some given ρ, l and v.

Proof. Immediate when considering the stores as function graphs: ⊑ is the inclusion, • \ ρ a relative complement, and • + {l → v} a disjoint union (preceded by • \ (l, v ′ ) when l is already bound to some v ′ ).

Before we prove that using minimal stores is equivalent to using full stores, we need an alphaconversion lemma, which allows us to rename locations in the store, provided the new location does not already appear in the store or the environments. It is used when choosing a fresh location for the (call) rule in proofs by induction.

Lemma 2.19 (Alpha-conversion). If M s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ then, for all l, for all l ′ appearing neither in s nor in F nor in ρ • ρ T , M s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /l] v s ′ [l ′ /l] .
Moreover, both derivations have the same height.

Proof. By induction on the height of the derivation. For the (call) case, we must ensure that the fresh locations l i do not clash with l ′ . In case they do, we conclude by applying the induction hypotheses twice: first to rename the clashing l i into a fresh l ′ i , then to rename l into l ′ . Two preliminary elementary remarks. First, provided l ′ appears neither in ρ or ρ T , nor in s,

(s \ ρ)[l ′ /l] = (s[l ′ /l]) \ (ρ[l ′ /l]) and (ρ T • ρ)[l ′ /l] = ρ T [l ′ /l] • ρ[l ′ /l]. Moreover, if M s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ , then dom(s ′ ) = dom(s) \ ρ T (straightforward by induction).
This leads to:

ρ T = ε ⇒ dom(s ′ ) = dom(s).
By induction on the height of the derivation, because the induction hypothesis must be applied twice in the case of the (call) rule.

(call) ∀i, dom(s i ) = dom(s i+1 ). Thus, ∀i, l ′ / ∈ dom(s i ). This leads, by the induction hypotheses, to

∀i, a si[l ′ /l] i |(ρT •ρ)[l ′ /l] ≡≡≡≡≡≡≡≡≡⇛ F v si+1[l ′ /l] i F [l ′ /l] Moreover , F ′ is part of F . As a result, since l ′ does not appear in F , it does not appear in F ′ , nor in F ′ + {f → F f }. It does not appear in ρ ′ either (since ρ ′ is part of F ′ ).
On the other hand, there might be some j such that l j = l ′ , so l ′ might appear in ρ ′′ . In that case, we apply the induction hypotheses a first time to rename l j in some l ′ j = l ′ . One can chose l ′ j such that it does not appear in s n+1 , F ′ + {f → F f } nor in ρ ′′ • ρ. As a result, l ′ j is fresh. Since l j is fresh too, and does not appear in dom(s ′ ) (because of our preliminary remarks), this leads to a mere substitution in ρ ′′ :

b sn+1+{li[l ′ j /lj ] →vi} ρ ′′ [l ′ j /lj ]|ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′
Once this (potentially) disturbing l j has been renamed (we ignore it in the rest of the proof), we apply the induction hypotheses a second time to rename l to l ′ :

b (sn+1+{li →vi})[l ′ /l] ρ ′′ [l ′ /l]|ρ ′ [l ′ /l] ≡≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′ [l ′ /l] Now, (s n+1 + {l i → v i })[l ′ /l] = s n+1 [l ′ /l] + {l i → v i }. Moreover, F [l ′ /l] f = [λx 1 . . . x n .b, ρ ′ [l ′ /l], F ′ [l ′ /l]] and (F ′ + {f → F f })[l ′ /l] = F ′ [l ′ /l] + {f → F [l ′ /l] f } Finally, ρ ′′ [l ′ /l] = ρ ′′ . Hence: f (a 1 . . . a n ) s1[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /l] v s ′ [l ′ /l]\ρT [l ′ /l] . (val) v s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] v s[l ′ /l]\ρT [l ′ /l] (var) s[l ′ /l](ρ T [l ′ /l] • ρ[l ′ /l] x) = s(ρ T • ρ x) = v implies x s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] v s[l ′ /l]\ρT [l ′ /l]
(assign) By the induction hypotheses,

a s[l ′ /l] |(ρT •ρ)[l ′ /l] ≡≡≡≡≡≡≡≡≡⇛ F [l ′ /] v s ′ [l ′ /] Let s ′′ = s ′ + {ρ T • ρ x → v}. Then, s ′ [l ′ /l] + {(ρ T • ρ)[l ′ /l] x → v} = s ′′ [l ′ /l] Hence x := a s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] 1 s ′′ [l ′ /l]\ρT [l ′ /l]
(seq) By the induction hypotheses,

a s[l ′ /l] |(ρT •ρ)[l ′ /l] ≡≡≡≡≡≡≡≡≡⇛ F [l ′ /] v s ′ [l ′ /l]
Besides, dom(s ′ ) = dom(s), therefore l ′ / ∈ dom(s ′ ). Then, by the induction hypotheses,

b s ′ [l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] v ′ s ′′ [l ′ /l] Hence a ; b s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] v ′ s ′′ [l ′ /l]
(if-true) and (if-false) are proved similarly to (seq).

(letrec) Since l ′ appears neither in ρ ′ nor in F , it does not appear in F ′ either. By the induction hypotheses,

b s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ [l ′ /l] v s ′ [l ′ /l] Moreover, F ′ [l ′ /l] = F [l ′ /l] + {f → [λx 1 . . . x n .a, ρ ′ [l ′ /l], F ]} Hence letrec f (x 1 . . . x n ) = a in b s ρT [l ′ /l]|ρ[l ′ /l] ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F [l ′ /] v s ′
To prove that using minimal stores is correct, we need to extend them so as to recover the full stores of naive reduction. The following lemma shows that extending a store before an (intermediate) reduction extends the resulting store too: Lemma 2.20 (Extending a store in a derivation).

Given the reduction M

s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ , then ∀t ⊒ s, ∃t ′ ⊒ s ′ , M t ρT |ρ ≡ ≡≡≡≡ ⇛ F v t ′ .
Moreover, both derivations have the same height.

Proof. By induction on the height of the derivation. The most interesting case is (call), which requires alpha-converting a location (hence the induction on the height rather than the structure of the derivation).

(var), (val) and (assign) are straightforward by the induction hypotheses and Property 2.18; (seq), (if-true), (if-false) and (letrec) are straightforward by the induction hypotheses.

(call) Let t 1 ⊒ s 1 . By the induction hypotheses,

∃t 2 ⊒ s 2 , a t1 1 |ρT •ρ ≡≡≡≡≡⇛ F v t2 1 ∃t i+1 ⊒ s i+1 , a ti i |ρT •ρ ≡≡≡≡≡⇛ F v ti+1 i ∃t n+1 ⊒ s n+1 , a tn n |ρT •ρ ≡≡≡≡≡⇛ F v tn+1 n
The locations l i might belong to dom(t n+1 ) and thus not be fresh. By alpha-conversion (Lemma 2.19), we chose fresh l ′ i (not in Im(ρ ′ ) and dom(s ′ )) such that

b sn+1+{l ′ i →vi} (l ′ i ,vi)|ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′ By Property 2.18, t n+1 + {l ′ i → v i } ⊒ s n+1 + {l ′ i → v i }.
By the induction hypotheses, (assign) Let t ⊒ s. By the induction hypotheses,

∃t ′ ⊒ s ′ , b tn+1+{l ′ i →vi} (l ′ i ,vi)|ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v t ′ Moreover, t ′ \ ρ T ⊒ s ′ \ ρ T . Hence, f (a 1 . . . a n ) t1 ρT |ρ ≡ ≡≡≡≡ ⇛ F v t ′ \ρT . (var) Let t ⊒ s. v t ρT |ρ ≡ ≡≡≡≡ ⇛ F v t\ρT and ∃t ′ = t \ ρ T ⊒ s \ ρ T = s ′ (Property 2.18). (
∃t ′ ⊒ s ′ , a t |ρT •ρ ≡≡≡≡≡⇛ F v t ′ Hence, x := a t ρT |ρ ≡ ≡≡≡≡ ⇛ F 1 t ′ +{l →v}\ρT concludes, since t ′ + {l → v} \ ρ T ⊒ t ′ + {l → v} \ ρ T (Property 2.18).
(seq) Let t ⊒ s. By the induction hypotheses,

∃t ′ ⊒ s ′ , a t |ρT •ρ ≡≡≡≡≡⇛ F v t ′ ∃t ′′ ⊒ s ′′ , b t ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ t ′′ Hence, ∃t ′′ ⊒ s ′′ , a ; b t ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ t ′′
(if-true) and (if-false) are proved similarly to (seq).

(letrec) Let t ⊒ s. By the induction hypotheses,

∃t ′ ⊒ s ′ , b s ρT |ρ ≡ ≡≡≡≡ ⇛ F ′ v s ′ Hence, ∃t ′ ⊒ s ′ , letrec f (x 1 . . . x n ) = a in b s ρT |ρ ≡ ≡≡≡≡ ⇛ F v t ′
Now we can show the required lemmas and prove the equivalence between the intermediate and naive reduction rules.

Lemma 2.21 (Intermediate implies naive).

If M s ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ then ∃t ′ ⊒ s ′ , M s ρT •ρ -----→ F v t ′ .
Proof. By induction on the height of the derivation, because some stores are modified during the proof. The interesting cases are (seq) and (call), where Lemma 2.20 is used to extend intermediary stores. Other cases are straightforward by Property 2.18 and the induction hypotheses.

(seq) By the induction hypotheses,

∃t ′ ⊒ s ′ , a s ρ ---→ F v t ′ . Moreover, b s ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ s ′′ .
Since t ′ ⊒ s ′ , Lemma 2.20 leads to:

∃t ⊒ s ′′ , b t ′ ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ t
and the height of the derivation is preserved. By the induction hypotheses,

∃t ′′ ⊒ t, b t ′ ρ ---→ F v ′ t ′′
Hence, since ⊑ is transitive (Property 2.18),

∃t ′′ ⊒ s ′′ , a ; b s ρ ---→ F v ′ t ′′ .
(call) Similarly to the (seq) case, we apply the induction hypotheses and Lemma 2.20:

∃t 2 ⊒ s 2 , a s1 1 ρ ---→ F v t2 1 (Induction) ∃t ′ i+1 ⊒ s i+1 , a ti i |ρT •ρ ≡≡≡≡≡⇛ F v t ′ i+1 i (Lemma 2.20) ∃t i+1 ⊒ t ′ i+1 ⊒ s i+1 , a ti i ρ ---→ F v ti+1 i (Induction) ∃t ′ n+1 ⊒ s n+1 , a tn n |ρT •ρ ≡≡≡≡≡⇛ F v t ′ n+1 n (Lemma 2.20) ∃t n+1 ⊒ t ′ n+1 ⊒ s n+1 , a tn n ρ ---→ F v tn+1 n (Induction)
The locations l i might belong to dom(t n+1 ) and thus not be fresh. By alpha-conversion (Lemma 2.19), we choose a set of fresh l ′ i (not in Im(ρ ′ ) and dom(s ′ )) such that

b sn+1+{l ′ i →vi} (l ′ i ,vi)|ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′ .
By Property 2.18,

t n+1 + {l ′ i → v i } ⊒ s n+1 + {l ′ i → v i }. Lemma 2.20 leads to, ∃t ⊒ s ′ , b tn+1+{l ′ i →vi} (l ′ i ,vi)|ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v t .
By the induction hypotheses,

∃t ′ ⊒ t ⊒ s ′ , b tn+1+{l ′ i →vi} (l ′ i ,vi)•ρ ′ -----------→ F ′ +{f →F f } v t ′ . Moreover, t ′ \ ρ T ⊒ s ′ \ ρ T . Hence, f (a 1 . . . a n ) s1 ρ ---→ F v t ′ \ρT . (val) v s ρ ---→ F v t ′ with t ′ = s ⊒ s \ ρ T = s ′ . (var) x s ρ ---→ F s l s ′′ with t ′ = s ⊒ s \ ρ T = s ′ .
(assign) By the induction hypotheses,

∃s ′′ ⊒ s ′ , a s ρ ---→ F v t ′ Hence, x := a s ρ ---→ F 1 t ′ +{l →v} concludes since t ′ + {l → v} ⊒ s ′ + {l → v} (Property 2.18).
(if-true) and (if-false) are proved similarly to (seq).

(letrec) By the induction hypotheses,

∃t ′ ⊒ s ′ , b s ρ ----→ F ′ v s ′ . Hence, ∃t ′ ⊒ s ′ , letrec f (x 1 . . . x n ) = a in b s ρ ---→ F v t ′ .
The proof of the converse property -i.e. if a term reduces in the naive reduction rules, it reduces in the intermediate reduction rules too -is more complex because the naive reduction rules provide very weak invariants about stores and environments. For that reason, we add an hypothesis to ensure that every location appearing in the environments ρ, ρ T and F also appears in the store s:

Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(s).
Moreover, since stores are often larger in the naive reduction rules than in the intermediate ones, we need to generalise the induction hypothesis.

Lemma 2.22 (Naive implies intermediate). Assume Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(s). Then, M s ρT •ρ -----→ F v s ′ implies ∀t ⊑ s such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t), M t ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ | dom(t)\Im(ρ T ) .
Proof. By induction on the structure of the derivation.

(val) Let t ⊑ s. Then

t \ ρ T = s| dom(t)\Im(ρT ) because s| dom(t) = t = s ′ | dom(t)\Im(ρT ) because s ′ = s Hence, v t ρT |ρ ≡ ≡≡≡≡ ⇛ F v t\ρT . (var) Let t ⊑ s such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t). Note that l ∈ Im(ρ T • ρ) ⊂ dom(t) implies t l = s l. Then, t \ ρ T = s| dom(t)\Im(ρT ) because s| dom(t) = t = s ′ | dom(t)\Im(ρT ) because s ′ = s
Hence,

x t ρT |ρ ≡ ≡≡≡≡ ⇛ F t l t\ρT .
(assign) Let t ⊑ s such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t). By the induction hypotheses, since Im(ε) = ∅,

a t |ρT •ρ ≡≡≡≡≡⇛ F v s ′ | dom(t) Note that l ∈ Im(ρ T • ρ) ⊂ dom(t) implies l ∈ dom(s ′ | dom(t) ). Then (s ′ | dom(t) + {l → v}) \ ρ T = (s ′ + {l → v})| dom(t) \ ρ T because l ∈ dom(s ′ | dom(t) ) = (s ′ + {l → v})| dom(t)\Im(ρT )
Hence,

x := a s ρT |ρ

≡ ≡≡≡≡ ⇛ F 1 (s ′ | dom(t) +{l →v})\ρT . (seq) Let t ⊑ s such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t)
. By the induction hypotheses, since Im(ε) = ∅,

a t |ρT •ρ ≡≡≡≡≡⇛ F v s ′ | dom(t) Moreover, s ′ | dom(t) ⊑ s ′ and Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(s ′ | dom(t) ) = dom(t)
. By the induction hypotheses, this leads to:

b s ′ | dom(t) ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ s ′′ | dom(s ′ | dom(t) )\Im(ρ T ) .
Hence, with dom(s

′ | dom(t) ) = dom(t), a ; b t ρT |ρ ≡ ≡≡≡≡ ⇛ F v ′ s ′′ | dom(t)\Im(ρ T ) .
(if-true) and (if-false) are proved similarly to (seq).

(letrec

) Let t ⊑ s such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t). Loc(F ′ ) = Loc(F ) ∪ Im(ρ T • ρ) implies Im(ρ T • ρ) ∪ Loc(F ′ ) ⊂ dom(t).
Then, by the induction hypotheses,

b t ρT |ρ ≡ ≡≡≡≡ ⇛ F ′ v s ′ | dom(t)\Im(ρ T ) .
Hence,

letrec f (x 1 . . . x n ) = a in b t ρT |ρ ≡ ≡≡≡≡ ⇛ F v s ′ | dom(t)\Im(ρ T ) . (call) Let t ⊑ s 1 such that Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(t)
. Note the following equalities:

s 1 | dom(t) = t s 2 | dom(t) ⊑ s 2 Im(ρ T • ρ) ∪ Loc(F ) ⊂ dom(s 2 | dom(t) ) = dom(t) s 3 | dom(s2| dom(t) ) = s 3 | dom(t)
By the induction hypotheses, they yield:

a t 1 |ρT •ρ ≡≡≡≡≡⇛ F v s2| dom(t) 1 a s2| dom(t) 2 |ρT •ρ ≡≡≡≡≡⇛ F v s3| dom(t) 1 ∀i, a si| dom(t) i |ρT •ρ ≡≡≡≡≡⇛ F v si+1| dom(t) i Moreover, s n+1 | dom(t) ⊑ s n+1 implies s n+1 | dom(t) + {l i → v i } ⊑ s n+1 + {l i → v i } (Property 2.18) and: Im(ρ ′′ • ρ ′ ) ∪ Loc(F ′ + {f → F f }) = Im(ρ ′′ ) ∪ (Im(ρ ′ ) ∪ Loc(F ′ )) ⊂ {l i } ∪ Loc(F ) ⊂ {l i } ∪ dom(t) ⊂ dom(s n+1 | dom(t) + {l i → v i })
Then, by the induction hypotheses,

b sn+1| dom(t) +{li →vi} ρ ′′ |ρ ′ ≡ ≡≡≡≡≡≡≡≡≡≡ ⇛ F ′ +{f →F f } v s ′ | dom(s n+1 | dom(t) +{l i →v i })\Im(ρ ′′ ) 20
Finally,

s ′ | dom(sn+1| dom(t) +{li →vi})\Im(ρ ′′ ) \ ρ T = s ′ | dom(t)∪{li}\{li} \ ρ T = s ′ | dom(t) \ ρ T = (s ′ \ ρ T )| dom(t)\Im(ρT ) (by definition of • \ •) Hence, f (a 1 . . . a n ) t ρT |ρ ≡ ≡≡≡≡ ⇛ F v (s ′ \ρT )| dom(t)\Im(ρ T ) .

Correctness of lambda-lifting

In this section, we prove the correctness of lambda-lifting (Theorem 2.9, p. 5) by induction on the height of the optimised reduction. Section 2.4.1 defines stronger invariants and rewords the correctness theorem with them. Section 2.4.2 gives an overview of the proof. Sections 2.4.3 and 2.4.4 prove a few lemmas needed for the proof. Section 2.4.5 contains the actual proof of correctness.

Strengthened hypotheses

We need strong induction hypotheses to ensure that key invariants about stores and environments hold at every step. For that purpose, we define aliasing-free environments, in which locations may not be referenced by more than one variable, and local positions. They yield a strengthened version of liftable parameters (Definition 2.25). We then define lifted environments (Definition 2.26) to mirror the effect of lambda-lifting in lifted terms captured in closures, and finally reformulate the correctness of lambda-lifting in Theorem 2.28 with hypotheses strong enough to be provable directly by induction.

Definition 2.23 (Aliasing).

A set of environments E is aliasing-free when:

∀ρ, ρ ′ ∈ E, ∀x ∈ dom(ρ), ∀y ∈ dom(ρ ′ ), ρ x = ρ ′ y ⇒ x = y.
By extension, an environment of functions F is aliasing-free when Env(F ) is aliasing-free.

The notion of aliasing-free environments is not an artifact of our small language, but translates a fundamental property of the C semantics: distinct function parameters or local variables are always bound to distinct memory locations (Section 6.2.2, paragraph 6 in ISO/IEC 9899 [START_REF]Programming Languages -C[END_REF]).

A local position is any position in a term except inner functions. Local positions are used to distinguish functions defined directly in a term from deeper nested functions, because we need to enforce Invariant 3 (Definition 2.25) on the former only.

Definition 2.24 (Local position). Local positions are defined inductively as follows:

1.

M is in local position in M , x := M , M ; M , if M then M else M and f (M, . . . , M ). 2. N is in local position in letrec f (x 1 . . . x n ) = M in N .
We extend the notion of liftable parameter (Definition 2.8, p. 5) to enforce invariants on stores and environments. Definition 2.25 (Extended liftability). The parameter x is liftable in (M, F , ρ T , ρ) when:

1.

x is defined as the parameter of a function g, either in M or in F , 2. in both M and F , inner functions in g, named h i , are defined and called exclusively: (a) in tail position in g, or (b) in tail position in some h j (with possibly i = j), or (c) in tail position in M , 3. for all f defined in local position in M , x ∈ dom(ρ T • ρ) ⇔ ∃i, f = h i , 4. moreover, if h i is called in tail position in M , then x ∈ dom(ρ T ), 5. in F , x appears necessarily and exclusively in the environments of the h i 's closures, 6. F contains only compact closures and Env(F ) ∪ {ρ, ρ T } is aliasing-free.

We also extend the definition of lambda-lifting (Definition 2.6, p. 5) to environments, in order to reflect changes in lambda-lifted parameters captured in closures. Definition 2.26 (Lifted form of an environment).

If F f = [λx 1 . . . x n .b, ρ ′ , F ′ ] then (F ) * f = λx 1 . . . x n x. (b) * , ρ ′ | dom(ρ ′ )\{x} , (F ′ ) * when f = h i for some i [λx 1 . . . x n . (b) * , ρ ′ , (F ′ ) * ] otherwise
Lifted environments are defined such that a liftable parameter never appears in them. This property will be useful during the proof of correctness.

Lemma 2.27. If x is a liftable parameter in (M, F , ρ T , ρ), then x does not appear in (F ) * .

Proof. Since x is liftable in (M, F , ρ T , ρ), it appears exclusively in the environments of h i . By definition, it is removed when building (F ) * .

These invariants and definitions lead to a correctness theorem with stronger hypotheses.

Theorem 2.28 (Correctness of lambda-lifting). If x is a liftable parameter in (M, F , ρ T , ρ), then

M s ρT |ρ = ==== ⇒ F v s ′ implies (M ) s * ρT |ρ = ==== ⇒ (F ) * v s ′
Since naive and optimised reductions rules are equivalent (Theorem 2.13, p. 7), the proof of Theorem 2.9 (p. 5) is a direct corollary of this theorem.

Corollary 2.29. If x is a liftable parameter in M , then

∃t, M ε ε ---→ ε v t implies ∃t ′ , (M ) ε * ε ---→ ε v t ′ .

Overview of the proof

With the enhanced liftability definition, we have invariants strong enough to perform a proof by induction of the correctness theorem. This proof is detailed in Section 2.4.5. The proof is not by structural induction but by induction on the height of the derivation. This is necessary because, even with the stronger invariants, we cannot apply the induction hypotheses directly to the premises in the case of the (call) rule: we have to change the stores and environments, which means rewriting the whole derivation tree, before using the induction hypotheses.

To deal with this most difficult case, we distinguish between calling one of the lifted functions (f = h i ) and calling another function (either g, where x is defined, or any other function outside of g). Only the former requires rewriting; the latter follows directly from the induction hypotheses.

In the (call) rule with f = h i , issues arise when reducing the body b of the lifted function. During this reduction, indeed, the store contains a new location l ′ bound by the environment to the lifted variable x, but also contains the location l which contains the original value of x. Our goal is to show that the reduction of b implies the reduction of (b) * , with store and environments fulfilling the constraints of the (call) rule.

To obtain the reduction of the lifted body (b) * , we modify the reduction of b in a series of steps, using several lemmas:

-the location l of the free variable x is moved to the tail environment (Lemma 2.30); -the resulting reduction meets the induction hypotheses, which we apply to obtain the reduction of the lifted body (b) * ; -however, this reduction does not meet the constraints of the optimised reduction rules because the location l is not fresh: we rename it to a fresh location l ′ to hold the lifted variable (Lemma 2.31); -finally, since we renamed l to l ′ , we need to reintroduce a location l to hold the original value of x (Lemmas 2.32 and 2.33). The rewriting lemmas used in the (call) case are shown in Section 2.4.3.

For every other case, the proof consists in checking thoroughly that the induction hypotheses apply, in particular that x is liftable in the premises. These verifications consist in checking Invariants 3 to 6 of the extended liftability definition (Definition 2.25) -Invariants 1 and 2 are obvious enough not to be detailed. To keep the main proof as compact as possible, the most difficult cases of liftability, related to aliasing, are proven in some preliminary lemmas (Section 2.4.4).

One last issue arises during the induction when one of the premises does not contain the lifted variable x. In that case, the invariants do not hold, since they assume the presence of x. But it turns out that in this very case, the lifting function is the identity (since there is no variable to lift) and lambda-lifting is trivially correct.

Rewriting lemmas

Calling a lifted function has an impact on the resulting store: new locations are introduced for the lifted parameters and the earlier locations, which are not modified anymore, are hidden. Because of these changes, the induction hypotheses do not apply directly in the case of the (call) rule for a lifted function h i . We use the following four lemmas to obtain, through several rewriting steps, a reduction of lifted terms meeting the induction hypotheses.

-Lemma 2.30 shows that moving a variable from the non-tail environment ρ to the tail environment ρ T does not change the result, but restricts the domain of the store. It is used transform the original free variable x (in the non-tail environment) to its lifted copy (which is a parameter of h i , hence in the tail environment). -Lemma 2.31 handles alpha-conversion in stores and is used when choosing a fresh location. -Lemmas 2.32 and 2.33 finally add into the store and the environment a fresh location, bound to an arbitrary value. It is used to reintroduce the location containing the original value of x, after it has been alpha-converted to l ′ .

Lemma 2.30 (Switching to tail environment).

If M s ρT |(x,l)•ρ = ======= ⇒ F v s ′ and x / ∈ dom(ρ T ) then M s ρT •(x,l)|ρ = ======= ⇒ F v s ′ | dom(s ′ )\{l} .
Moreover, both derivations have the same height.

Proof. By induction on the structure of the derivation. For the (val), (var), (assign) and (call) cases, we use the fact that s

\ ρ T • (x, l) = s ′ | dom(s ′ )\{l} when s ′ = s \ ρ T . (val) v s ρT •(x,l)|ρ = ======= ⇒ F v s\ρT •(x,l) and s \ ρ T • (x, l) = s ′ | dom(s ′ )\{l} with s ′ = s \ ρ T . (var) y s ρT •(x,l)|ρ = ======= ⇒ F s l ′ s\ρT •(x,l) and s \ ρ T • (x, l) = s ′ | dom(s ′ )\{l} , with l ′ = ρ T • (x, l) • ρ y and s ′ = s \ ρ T .
(assign) By hypothesis, l) and

a s |ρT •(x,l)•ρ = ======== ⇒ F v s ′ hence y := a s ρT •(x,l)|ρ = ======= ⇒ F 1 s ′ +{l ′ →v}\ρT •(x,
s ′ + {l ′ → v} \ ρ T • (x, l) = s ′ | dom(s ′ )\{l} with l ′ = ρ T • (x, l) • ρ y and s ′ = s ′ + {l ′ → v} \ ρ T .
(seq) By hypothesis,

a s |ρT •(x,l)•ρ = ======== ⇒ F v s ′ and, by the induction hypotheses, b s ′ ρT •(x,l)|ρ = ======= ⇒ F v s ′′ | dom(s ′′ )\{l} hence a ; b s ρT •(x,l)|ρ = ======= ⇒ F v s ′′ | dom(s ′′ )\{l} .
(if-true) and (if-false) are proved similarly to (seq).

(letrec) By the induction hypotheses,

b s ρT •(x,l)|ρ = ======= ⇒ F ′ v s ′ | dom(s ′ )\{l} hence letrec f (x 1 . . . x n ) = a in b s ρT •(x,l)|ρ = ======= ⇒ F v s ′ | dom(s ′ )\{l}
(call) The hypotheses do not change, and the conclusion becomes:

f (a 1 . . . a n ) s1 ρT •(x,l)|ρ = ======= ⇒ F v s ′ \ρT •(x,l)
as expected, since

s ′ \ ρ T • (x, l) = s ′′ | dom(s ′′ )\{l} with s ′′ = s ′ \ ρ T Lemma 2.31 (Alpha-conversion). If M s ρT |ρ = ==== ⇒ F v s ′ then, for all l, for all l ′ appearing neither in s nor in F nor in ρ • ρ T , M s[l ′ /l] ρT [l ′ /l]|ρ[l ′ /l] = ========== ⇒ F [l ′ /l] v s ′ [l ′ /l]
Moreover, both derivations have the same height.

Proof. See Lemma 2.19, p. 2.19. Proof. By induction on the height of the derivation. The key idea is to add (k, u) to every store in the derivation tree. A collision might occur in the (call) rule, if there is some j such that l j = k. In that case, we need to rename l j to some fresh variable l ′ j = k (by alpha-conversion) before applying the induction hypotheses.

(call) By the induction hypotheses, ∀i, a

si+{k →u} i |ρT •ρ =====⇒ F v si+1+{k →u} i Because k does not appear in F , k / ∈ Loc(F ′ + {f → F f }) ⊂ Loc(F )
For the same reason, it does not appear in ρ ′ . On the other hand, there might be a j such that l j = k, so k might appear in ρ ′′ . In that case, we rename l j in some fresh l ′ j = k, appearing in neither s n+1 , nor F ′ or ρ ′′ • ρ ′ (Lemma 2.31). After this alpha-conversion, k does not appear in either

ρ ′′ • ρ ′ , F ′ + {f → F f }, or s n+1 + {l i → v i }. By the induction hypotheses, b sn+1+{li →vi}+{k →u} ρ ′′ |ρ ′ = ========== ⇒ F ′ +{f →F f } v s ′ +{k →u} Moreover, s ′ + {k → u} \ ρ T = s ′ \ ρ T + {k → u} (since k does not appear in ρ T ). Hence f (a 1 . . . a n ) s1+{k →u} ρT |ρ = ==== ⇒ F v s ′ +{k →u}\ρT . (val) v s+{k →u} ρT |ρ = ==== ⇒ F v s+{k →u}\ρT and s + {k → u} \ ρ T = s \ ρ T + {k → u} since k does not appear in ρ T . (var) x s+{k →u} ρT |ρ = ==== ⇒ F (s + {k → u}) l s+{k →u}\ρT , with s + {k → u} \ ρ T = s \ ρ T + {k → u}
a s+{k →u} |ρT •ρ =====⇒ F true s ′ +{k →u} b s ′ +{k →u} ρT |ρ = ==== ⇒ F v ′ s ′′ +{k →u} Hence a ; b s+{k →u} ρT |ρ = ==== ⇒ F v ′ s ′′ +{k →u}
(if-true) and (if-false) are proved similarly to (seq).

(letrec) The location k does not appear in F ′ , because it does not appear in either F or

ρ ′ ⊂ ρ T • ρ (F ′ = F + {f → [λx 1 . . . x n .a, ρ ′ , F ]}).
Then, by the induction hypotheses,

b s+{k →u} ρT |ρ = ==== ⇒ F ′ v s ′ +{k →u} Hence letrec f (x 1 . . . x n ) = a in b s+{k →u} ρT |ρ = ==== ⇒ F v s ′ +{k →u} .
Lemma 2.33 (Spurious variable in environments).

∀l, l ′ , M s ρT •(x,l)|ρ = ======= ⇒ F v s ′ iff M s ρT •(x,l)|(x,l ′ )•ρ = =========== ⇒ F v s ′
Moreover, both derivations have the same height.

Proof. See Lemma 2.14, p. 2.14.

Aliasing lemmas

We need three lemmas to show that environments remain aliasing-free during the proof by induction in Section 2.4.5. The first lemma states that concatenating two environments in an aliasing-free set yields an aliasing-free set. The other two prove that the aliasing invariant (Invariant 6, Definition 2.25) holds in the context of the (call) and (letrec) rules, respectively.

Lemma 2.34 (Concatenation). If E ∪ {ρ, ρ ′ } is aliasing-free then E ∪ {ρ • ρ ′ } is aliasing-free.
Proof. By exhaustive check of cases. We want to prove

∀ρ 1 , ρ 2 ∈ E ∪ {ρ • ρ ′ }, ∀x ∈ dom(ρ 1 ), ∀y ∈ dom(ρ 2 ), ρ 1 x = ρ 2 y ⇒ x = y.
given that

∀ρ 1 , ρ 2 ∈ E ∪ {ρ, ρ ′ }, ∀x ∈ dom(ρ 1 ), ∀y ∈ dom(ρ 2 ), ρ 1 x = ρ 2 y ⇒ x = y. If ρ 1 ∈ E and ρ 2 ∈ E, immediate. If ρ 1 ∈ {ρ • ρ ′ }, ρ 1 x = ρ x or ρ ′
x. This is the same for ρ 2 .

Then ρ 1 x = ρ 2 y is equivalent to ρ x = ρ ′ y (or some other combination, depending on x, y, ρ 1 and ρ 2 ) which leads to the expected result.

Lemma 2.35 (Aliasing in (call) rule). Assume that, in a (call) rule, -

F f = [λx 1 . . . x n .b, ρ ′ , F ′ ],
-Env(F ) is aliasing-free, and -ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n ), with fresh and distinct locations l i . Then Env(

F ′ + {f → F f }) ∪ {ρ ′ , ρ ′′ } is also aliasing-free. Proof. Let E = Env(F ′ + {f → F f }) ∪ {ρ ′ }.
We know that E ⊂ Env(F ) so E is aliasing-free We want to show that adding fresh and distinct locations from ρ ′′ preserves this lack of freedom. More precisely, we want to show that

∀ρ 1 , ρ 2 ∈ E ∪ {ρ ′′ }, ∀x ∈ dom(ρ 1 ), ∀y ∈ dom(ρ 2 ), ρ 1 x = ρ 2 y ⇒ x = y given that ∀ρ 1 , ρ 2 ∈ E, ∀x ∈ dom(ρ 1 ), ∀y ∈ dom(ρ 2 ), ρ 1 x = ρ 2 y ⇒ x = y.
We reason by checking of all cases. If

ρ 1 ∈ E and ρ 2 ∈ E, immediate. If ρ 1 = ρ 2 = ρ ′′ then ρ ′′ x = ρ ′′ y ⇒ x = y holds because the locations of ρ ′′ are distinct. If ρ 1 = ρ ′′ and ρ 2 ∈ E then ρ 1 x = ρ 2 y ⇒ x = y holds because ρ 1 x = ρ 2 y (by freshness hypothesis).
Lemma 2.36 (Aliasing in (letrec) rule). If Env(F ) ∪ {ρ, ρ T } is aliasing free, then, for all x i ,

Env(F ) ∪ {ρ, ρ T } ∪ {ρ T • ρ | dom(ρT •ρ)\{x1...xn} } is aliasing free. Proof. Let E = Env(F ) ∪ {ρ, ρ T } and ρ ′′ = ρ T • ρ| dom(ρT •ρ)\{x1...xn} . Adding ρ ′′ ,
a restricted concatenation of ρ T and ρ, to E preserves aliasing freedom, as in the proof of Lemma 2.34. If ρ 1 ∈ E and ρ 2 ∈ E, immediate. If ρ 1 ∈ {ρ ′′ }, ρ 1 x = ρ x or ρ ′ x. This is the same for ρ 2 . Then ρ 1 x = ρ 2 y is equivalent to ρ x = ρ ′ y (or some other combination, depending on x, y, ρ 1 and ρ 2 ) which leads to the expected result.

Proof of correctness

We finally show Theorem 2.28.

Theorem 2.28. If x is a liftable parameter in (M, F , ρ T , ρ), then

M s ρT |ρ = ==== ⇒ F v s ′ implies (M ) s * ρT |ρ = ==== ⇒ (F ) * v s ′
Assume that x is a liftable parameter in (M, F , ρ T , ρ). The proof is by induction on the height of the reduction of

M s ρT |ρ = ==== ⇒ F v s ′ .
To keep the proof readable, we detail only the non-trivial cases when checking the invariants of Definition 2.25 to ensure that the induction hypotheses hold.

(call) -first case First, we consider the most interesting case where there exists i such that

f = h i . The variable x is a liftable parameter in (h i (a 1 . . . a n ), F , ρ T , ρ) hence in (a i , F , ε, ρ T • ρ) too.
Indeed, the invariants of Definition 2. By the induction hypotheses, we get

(a i ) * si |ρT •ρ =====⇒ (F ) * v si+1 i
.

By definition of lifting, (h i (a 1 . . . a n )) * = h i ((a 1 ) * , . . . , (a n ) * , x). But x is not a liftable parameter in (b, F ′ , ρ ′′ , ρ ′ ) since the Invariant 4 might be broken: x / ∈ dom(ρ ′′ ) (x is not a parameter of h i ) but h j might appear in tail position in b.

On the other hand, we have x ∈ dom(ρ ′ ): since, by hypothesis, x is a liftable parameter in (h i (a 1 . . . a n ), F , ρ T , ρ), it appears necessarily in the environments of the closures of the h i , such as ρ ′ . This allows us to split ρ ′ into two parts: ρ ′ = (x, l) • ρ ′′′ . It is then possible to move (x, l) to the tail environment, according to Lemma 2.30:

b sn+1+{li →vi} ρ ′′ (x,l)|ρ ′′′ ===========⇒ F ′ +{f →F f } v s ′ | dom(s ′ )\{l}
This rewriting ensures that x is a liftable parameter in (b,

F ′ + {f → F f }, ρ ′′ • (x, l), ρ ′′′ ).
Indeed, the invariants of Definition 2.25 hold:

- By the induction hypotheses,

(b) sn+1+{li →vi} * ρ ′′ (x,l)|ρ ′′′ ============= ⇒ (F ′ +{f →F f }) * v s ′ | dom(s ′ )\{l}
The l location is not fresh: it must be rewritten into a fresh location, since x is now a parameter of h i . Let l ′ be a location appearing in neither (

F ′ + {f → F f }) * , nor s n+1 + {l i → v i } or ρ ′′ • ρ T ′ .
Then l ′ is a fresh location, which is to act as l in the reduction of (b) * . We will show that, after the reduction, l ′ is not in the store (just like l before the lambdalifting). In the meantime, the value associated to l does not change (since l ′ is modified instead of l).

Lemma 2.27 implies that x does not appear in the environments of (F ) * , so it does not appear in the environments of (F ′ + {f → F f }) * ⊂ (F ) * either. As a consequence, lack of aliasing implies by Definition 2.23 that the label l, associated to x, does not appear in (

F ′ + {f → F f }) * either, so (F ′ + {f → F f }) * [l ′ /l] = (F ′ + {f → F f }) * .
Moreover, l does not appear in s ′ | dom(s ′ )\{l} . By alpha-conversion (Lemma 2.31, since l ′ does not appear in the store or the environments of the reduction, we rename l to l ′ :

(b) sn+1[l ′ /l]+{li →vi} * ρ ′′ (x,l ′ )|ρ ′′′ ============= ⇒ (F ′ +{f →F f }) * v s ′ | dom(s ′ )\{l} .
We want now to reintroduce l. Let v x = s n+1 l. The location l does not appear in s n+1 [l ′ /l] + {l i → v i }, (F ′ + {f → F f }) * , or ρ ′′ (x, l ′ ) • ρ ′′′ . Thus, by Lemma 2.32, (b)

sn+1[l ′ /l]+{li →vi}+{l →vx} * ρ ′′ (x,l ′ )|ρ ′′′ ============= ⇒ (F ′ +{f →F f }) * v s ′ | dom(s ′ )\{l} +{l →vx} .
Since

s n+1 [l ′ /l] + {l i → v i } + {l → v x } = s n+1 [l ′ /l] + {l → v x } + {l i → v i } because ∀i, l = l i = s n+1 + {l ′ → v x } + {l i → v i } because v x = s n+1 l = s n+1 + {l i → v i } + {l ′ → v x } because ∀i, l ′ = l i and s ′ | dom(s ′ )\{l} + {l → v x } = s ′ + {l → v x },
sn+1+{li →vi}+{l ′ →vx} * ρ ′′ (x,l ′ )|(x,l)•ρ ′′′ = ============ ⇒ (F ′ +{f →F f }) * v s ′ +{l →vx} .
Hence the result:

(call) (F ) * h i = [λx 1 . . . x n x. (b) * , ρ ′ , (F ′ ) * ] ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n )(x, ρ T x)
l ′ and l i fresh and distinct ∀i,

(a i ) * si |ρT •ρ =====⇒ (F ) * v si+1 i (x) * sn+1 |ρT •ρ =====⇒ (F ) * v sn+1 x (b) sn+1+{li →vi}+{l ′ →vx} * ρ ′′ (x,l ′ )|ρ ′ = ============ ⇒ (F ′ +{f →F f }) * v s ′ +{l →vx} (h i (a 1 . . . a n )) * s1 ρT |ρ = ==== ⇒ (F ) * v s ′ +{l →vx}\ρT
Since l ∈ dom(ρ T ) (because x is a liftable parameter in (h i (a 1 . . . a n ), F , ρ T , ρ)), the extraneous location is reclaimed as expected: By the induction hypotheses, we get

s ′ + {l → v x } \ ρ T = s ′ \ ρ T . (
(a i ) * si |ρT •ρ =====⇒ (F ) * v si+1 i
, and, by Definition 2.6, (f (a 1 . . . a n )) * = f ((a 1 ) * , . . . , (a n ) * ).

If x is not defined in b or F , then () * is the identity function and can trivially be applied to the reduction of b. Otherwise, x is a liftable parameter in (b,

F ′ + {f → F f }, ρ ′′ , ρ ′ ).
Indeed, the invariants of Definition 2.25 hold. Assume that x is defined as a parameter of some function g, in either b or F :

-Invariant 3: We have to distinguish the cases where f = g (with x ∈ dom(ρ ′′ )) and f = g (with x / ∈ dom(ρ ′′ ) and x / ∈ dom(ρ ′ )). In both cases, the result is immediate by the induction hypotheses.

-Invariant 4: If f = g, the premise cannot hold (by the induction hypotheses, Invariant 2).

If f = g, x ∈ dom(ρ ′′ ) (by the induction hypotheses, Invariant 2 (assign)

sn+1+{li →vi} * ρ ′′ |ρ ′ = ============ ⇒ (F ′ +{f →F f }) * v s ′ 29 hence: (call) (F ) * f = [λx 1 . . . x n . (b) * , ρ ′ , (F ′ ) * ] ρ ′′ = (x 1 , l 1 ) • . . . • (x n , l n ) l i fresh and distinct ∀i, (a i ) * si |ρT •ρ =====⇒ (F ) * v si+1 i (b) sn+1+{li →vi} * ρ ′′ |ρ ′ = ============ ⇒ (F ′ +{f →F f }) * v s ′ (f (a 1 . . . a n )) * s1 ρT |ρ = ==== ⇒ (F ) * v s ′ \ρT (letrec) The parameter x is a liftable in (letrec f (x 1 . . . x n ) = a in b, F , ρ T , ρ) so x is a liftable parameter in (b, F ′ , ρ T , ρ) too. Indeed,
s * ρT |ρ = ===== ⇒ (F ′ ) * v s ′ . If f = h i , (letrec f (x 1 . . . x n ) = a in b) * = letrec f (x 1 . . . x n ) = (a) * in (b) * hence, by definition of (F ′ ) * , (letrec) (b) s * ρT |ρ = ===== ⇒ (F ′ ) * v s ′ ρ ′ = ρ T • ρ| dom(ρT •ρ)\{x1...xn} (F ′ ) * = (F ) * +{f → [λx 1 . . . x n . (a) * , ρ ′ , F ]} (letrec f (x 1 . . . x n ) = a in b) * s ρT |ρ = ==== ⇒ (F ) * v s ′ On the other hand, if f = h i , (letrec f (x 1 . . . x n ) = a in b) * = letrec f (x 1 . . . x n x) = (a) * in (b) * hence, by definition of (F ′ ) * , (letrec) (b) s * ρT |ρ = ===== ⇒ (F ′ ) * v s ′ ρ ′ = ρ T • ρ| dom(ρT •ρ)\{x1...xnx} (F ′ ) * = (F ) * +{h i → [λx 1 . . . x n x. (a) * , ρ ′ , F ]} (letrec h i (x 1 . . . x n ) = a in b) * s ρT |ρ = ==== ⇒ (F ) * v s ′ (val) (v) * = v so (val) (v) * s ρT |ρ = ==== ⇒ (F ) * v s\ρT (
(a) * s |ρT •ρ =====⇒ (F ) * v s ′ ρ T • ρ y = l ∈ dom s ′ (y := a) * s ρT |ρ = ==== ⇒ (F ) * 1 s ′ +{l →v}\ρT (seq)
The parameter x is liftable in (a ; b, F , ρ T , ρ). If x is not defined in a or F , then () * is the identity function and can trivially be applied to the reduction of a. Otherwise, x is a liftable parameter in (a, F , ε, ρ T • ρ). Indeed, the invariants of Definition 2.25 hold:

-Invariant 6: Lemma 2.34, p. 26. The other invariants hold trivially.

If x is not defined in b or F , then () * is the identity function and can trivially be applied to the reduction of b. Otherwise, x is a liftable parameter in (b, F , ρ T , ρ). Indeed, the invariants of Definition 2.25 hold trivially.

(a) * s |ρT •ρ =====⇒ (F ) * v s ′ (b) * s ′ ρT |ρ = ==== ⇒ (F ) * v ′ s ′′ (a ; b) * s ρT |ρ = ==== ⇒ (F ) * v ′ s ′′ (seq)
(if-true) and (if-false) are proved similarly to (seq).

CPS conversion

In this section, we prove the correctness of the CPS-conversion performed by the CPC translator. This conversion is defined only on a subset of C programs that we call CPS-convertible terms (Section 3.1). We first show that the early evaluation of function parameters in CPS-convertible terms is correct (Section 3.2). To simplify the proof of correctness of CPS-conversion, we then introduce small-step reduction rules featuring contexts and early evaluation (Section 3.3). In Section 3.4, we define CPS terms, with the push and invoke operators to build and execute continuations, and the associated reduction rules. Since the syntax of CPS-terms does not ensure a correct reduction, we also define well-formed CPS-terms, which are the image of CPS-convertible terms by CPS-conversion.

The proof of correctness of CPS-conversion is finally carried out in Section 3.5. It consists merely in checking that the reduction rules for CPS-convertible terms and well-formed CPS-terms execute in lock-step.

CPS-convertible form

CPS conversion is not defined for every C function; instead, we restrict ourselves to a subset of functions, which we call the CPS-convertible subset. The CPS-convertible form restricts the calls to cps functions to make it straightforward to capture their continuation. In CPS-convertible form, a call to a cps function f is either in tail position, or followed by a tail call to another cps function whose parameters are non-shared variables that cannot be modified by f.

In the C language, we define the CPS-convertible form as follows:

Definition 3.

x = f(e 1 , ..., e n ); return g(x, y 1 , ..., y n );

f(e 1 , ..., e n ); return g(x, y 1 , ..., y n );

f(e 1 , ..., e n ); return;

f(e 1 , ..., e n ); g(x, y 1 , ..., y n ); return;

x = f(e 1 , ..., e n ); g(x, y 1 , ..., y n ); return;

Note the use of return to explicitly mark calls in tail position. The forms (3) to (6) are only necessary to handle the cases where f and g return void; in the rest of the proof, we ignore these cases that are a syntactical detail of the C language, and focus on the essential cases (1) and (2).

To prove the correctness of CPS-conversion, we need to express this definition in our small imperative language. This is done by defining CPS-convertible terms, which are a subset of the terms introduced in Definition 2.1 (Section 2.1). A program in CPS-convertible form consists of a set of mutually-recursive functions with no free variables, the body of each of which is a CPS-convertible term.

A CPS-convertible term has two parts: the head and the tail. The head is a (possibly empty) sequence of assignments, possibly embedded within conditional statements. The tail is a (possibly empty) sequence of function calls in a highly restricted form: their parameters are (side-effect free) expressions, except possibly for the last one, which can be another function call of the same form. Values and expressions are left unchanged. Since, dom(s) ⊂ dom(s ′ ), the second equality can be restricted to s ′ | dom(s)\Im(ρ) = s ′′ | dom(s)\Im(ρ) .

Hence, s| dom(s)\Im(ρ) = s ′′ | dom(s)\Im(ρ) .

(if-true) and (if-false) are proved similarly to (seq).

(letrec) doesn't occur since M is lambda-lifted. Finally, we can prove similarly to the (seq) case that s| dom(s)\Im(ρ) = s n+1 | dom(s)\Im(ρ) .

Hence, s| dom(s)\Im(ρ) = s ′ | dom(s)\Im(ρ) .

As a consequence, a tail of function calls cannot modify the current store, only extend it with the parameters of the called functions. Proof. We prove the corollary by induction on the structure of a tail. First remember that store extension (written ⊑) is a partial order over stores (Property 2.18), defined in Section 2.3.2 as follows: s ⊑ s ′ iff s ′ | dom(s) = s. The case ǫ is trivial. The case Q ; F is immediate by induction ((seq) rule), since ⊑ is transitive. Similarly, it is pretty clear that f (expr, . . . , expr, F ) follows by induction and transitivity from f (expr, . . . , expr) ((call) rule). We focus on this last case. Proof. Immediate induction on the structure of tails and expressions: Corollary 3.4 implies that s ⊑ s ′′ and ρ x ∈ dom(s) ensures that s(ρ x) = s ′′ (ρ x) in the relevant cases (namely the (seq) rule for Q ; F and the (call) rule for f (expr, . . . , expr, F )).

Small-step reduction

We define the semantics of CPS-convertible terms through a set of small-step reduction rules. We distinguish three kinds of reductions: → T to reduce the head of terms, → Q to reduce the tail, and → e to evaluate expressions. These rules describe a stack machine with a store σ to keep the value of variables. Since free and shared variables have been eliminated in earlier passes, there is a direct correspondence at any point in the program between variable names and locations, with no need to dynamically maintain an extra environment.

We use contexts as a compact representation for stacks. The head rules → T reduce triples made of a term, a context and a store: T, C[ ], σ . The tail rules → Q , which merely unfold tails with no need of a store, reduce couples of a tail and a context: Q, C[ ], . The expression rules do not need context to reduce, thus operating on couples made of an expression and a store: e, σ .

Contexts Contexts are sequences of function calls. In those sequences, function parameters shall be already evaluated: constant expressions are allowed, but not variables. As a special case, the last parameter might be a "hole" instead, written ⊖, to be filled with the return value of the next, nested function. -∀T, T = ǫ ⇒ T = invoke (by disjunction on the definition of ), -here, Q = invoke because (push f (expr, . . . , expr, ⊡) ; Q) is well-formed, -hence Q = ǫ. One checks easily that (T ) = T and (T ) = T .

To conclude the proof of isomorphism, we also need an (obviously bijective) mapping from contexts to continuations: The correctness theorem follows:

Theorem 3.17 (Correctness of CPS conversion). The and △ mappings are two bijections, the inverses of which are written and ▽ . They yield an isomorphism between reduction rules of CPS-convertible terms and CPS terms.

Proof. Lemma 3.15 ensures that is a bijection between CPS-convertible terms and well-formed CPS terms. Moreover, △ is an obvious bijection between contexts and continuations.

To complete the proof, we only need to apply , △ , and ▽ to CPS-convertible terms, contexts, well-formed CPS terms and continuations (respectively) in every reduction rule and check that we get a valid rule in the dual reduction system. The result is summarized in Figure 4.

Definition 2 . 1 (

 21 Values, expression and terms). Values are either boolean and integer constants or 1, a special value for functions returning void.v ::= 1 | true | false | n ∈ NExpressions are either values or variables. We deliberately omit arithmetic and boolean operators, with the sole concern of avoiding boring cases in the proofs. e ::= v | x | . . . Terms are consist of assignments, conditionals, sequences, recursive functions definitions and calls. T ::= e | x := T | if T then T else T | T ; T | letrec f (x 1 . . . x n ) = T in T | f (T, . . . , T )

Definition 2 . 3 (

 23 Environments of variables and functions). Environments of variables are defined inductively by ρ ::= ε | (x, l) • ρ, i.e. the empty domain function and ρ + {x → l} (respectively). Environments of functions associate function names to closures: F : {f, g, h, . . . } → {[λx 1 . . . x n .T, ρ, F ]}.

Figure 1 :

 1 Figure 1: "Naive" reduction rules

Definition 2 .

 2 11 (Compact closure and environment). A closure [λx 1

Figure 2 :

 2 Figure 2: Optimised reduction rules

Figure 3 :

 3 Figure 3: Intermediate reduction rules

  val) Let t ⊒ s. x t ρT |ρ ≡ ≡≡≡≡ ⇛ F t l t\ρT and ∃t ′ = t \ ρ T ⊒ s \ ρ T = s ′ (Property 2.18). Moreover, t l = s l because l ∈ dom(s) and t| dom(s) = s.

Lemma 2 .

 2 32 (Spurious location in store). If M s ρT |ρ = ==== ⇒ F v s ′ and k does not appear in either s, F or ρ T • ρ, then, for all value u, M s+{k →u} ρT |ρ = ==== ⇒ F v s ′ +{k →u} . Moreover, both derivations have the same height.

F 1 s

 1 since k does not appear in ρ T , and (s + {k → u}) l = s l since k = l (k does not appear in s). (assign) By the induction hypotheses, a s+{k →u} |ρT •ρ =====⇒ F v s ′ +{k →u} . And k = l (since k does not appear in s) then s ′ + {k → u} + {l → v} = s ′ + {l → v} + {k → u}. Moreover, k does not appear in ρ T then s ′ + {l → v} + {k → u} \ ρ T = s ′ + {l → v} \ ρ T + {k → u}. Hence x := a s+{k →u} ρT |ρ = ==== ⇒ ′ +{l →v}\ρT +{k →u} (seq) By the induction hypotheses,

25 hold: -Invariant 3 :

 3 By definition of a local position, every f defined in local position in a i is in local position in h i (a 1 . . . a n ), hence the expected property by the induction hypotheses. -Invariant 4: Immediate since the premise does not hold : since the a i are not in tail position in h i (a 1 . . . a n ), they cannot feature calls to h i (by Invariant 2). -Invariant 6: Lemma 2.34, p. 26. The other invariants hold trivially.

  we finish the rewriting by Lemma 2.33, (b)

  var) (y) * = y so (var) ρ T • ρ y = l ∈ dom s The parameter x is liftable in (y := a, F , ρ T , ρ) so in (a, F , ε, ρ T • ρ) too. Indeed, the invariants of Definition 2.25 hold: -Invariant 6: Lemma 2.34, p. 26. The other invariants hold trivially. By the induction hypotheses, we get (= a) * = y := (a) * , so :

  By the induction hypotheses, we get (a) b) * = (a) * ; (b) * , hence:

(

  assign) By the induction hypotheses, s| dom(s)\Im(ρ) = s ′ | dom(s)\Im(ρ) and l ∈ Im(ρ), hence s| dom(s)\Im(ρ) = (s ′ + {l → v})| dom(s)\Im(ρ) . (seq) By the induction hypotheses, s| dom(s)\Im(ρ) = s ′ | dom(s)\Im(ρ) and s ′ | dom(s ′ )\Im(ρ) = s ′′ | dom(s ′ )\Im(ρ) .

(

  call) By the induction hypotheses,(s n+1 + {l i → v i })| dom(sn+1+{li →vi})\Im(ρ ′′ •ρ ′ ) = s ′ | dom(sn+1+{li →vi})\Im(ρ ′′ •ρ ′ ) Since ρ ′ = ε, Im(ρ ′′ ) = {l i } and dom(s n+1 ) ∩ {l i } = ∅ (by freshness), (s n+1 + {l i → v i })| dom(sn+1) = s ′ | dom(sn+1) so s n+1 = s ′ | dom(sn+1) . Since dom(s) \ Im(ρ) ⊂ dom(s) ⊂ dom(s n+1 ),s n+1 | dom(s)\Im(ρ) = s ′ | dom(s)\Im(ρ) .

Corollary 3 . 4 .

 34 For every tail Q, Q s ρ ---→ F v s ′ implies s ⊑ s ′ .

  Lemma 3.3 implies:(s n+1 + {l i → v i })| dom(sn+1+{li →vi})\Im(ρ ′′ •ρ ′ ) = s ′ | dom(sn+1+{li →vi})\Im(ρ ′′ •ρ ′ ) . Since ρ ′ = ε, Im(ρ ′′ ) = {l i } and dom(s n+1 ) ∩ {l i } = ∅ (by freshness), (s n+1 + {l i → v i })| dom(sn+1) = s ′ | dom(sn+1) so s n+1 = s ′ | dom(sn+1) .The evaluation of expr parameters do not change the store: s n+1 = s. The expected result follows:s = s ′ | dom(s) , hence s ⊑ s ′ .This leads to the correctness of early evaluation.

Theorem 3 . 5 (

 35 Early evaluation). For every tailQ, Q s ρ ---→ F v s ′ implies Q[x\s(ρ x)] s ρ ---→ F v s ′(provided x ∈ dom(ρ) and ρ x ∈ dom(s)).

Definition 3 .

 3 6 (Contexts). Contexts are defined inductively:C ::= [ ] | C[[ ] ; f (v, . . . , v)] | C[[ ] ; f (v, . . . , v, ⊖)]

Definition 3 .

 3 16 (Conversion of contexts).([ ]) △ = ε (C[[ ] ; f (v 1 , . . . , v n )]) △ = f (v 1 , . . . , v n ) • C with (C[ ]) △ = C (C[[ ] ; f (v 1 , . . . , v n , ⊖)]) △ = f (v 1 , . . . , v n , ⊡) • C with (C[ ]) △ = C

  Invariant 3: Every function defined in local position in b is an inner function in h i so, by Invariant 2, it is one of the h i and x ∈ dom(ρ ′′ • (x, l) • ρ ′′′ ). -Invariant 4: Immediate since x ∈ dom(ρ ′′ • (x, l) • ρ ′′′ ). -Invariant 5: Immediate since F ′ is included in F . -Invariant 6: Immediate for the compact closures. Aliasing freedom is guaranteed by Lemma 2.35 (p. 26). The other invariants hold trivially.

  call) -second case We now consider the case where f is not one of the h i . The variable x is a liftable parameter in (f (a1 . . . a n ), F , ρ T , ρ) hence in (a i , F , ε, ρ T • ρ) too.Indeed, the invariants of Definition 2.25 hold: -Invariant 3: By definition of a local position, every f defined in local position in a i is in local position in f (a 1 . . . a n ), hence the expected property by the induction hypotheses. -Invariant 4: Immediate since the premise does not hold : the a i are not in tail position in f (a 1 . . . a n ) so they cannot feature calls to h i (by Invariant 2:). -Invariant 6: Lemma 2.34, p. 26. The other invariants hold trivially.

  ). -Invariant 5: Immediate since F ′ is included in F . -Invariant 6: Immediate for the compact closures. Aliasing freedom is guaranteed by Lemma 2.35 (p. 26).

	The other invariants hold trivially.
	By the induction hypotheses,
	(b)

  the invariants of Definition 2.25 hold: -Invariants 3 and 4: Immediate by the induction hypotheses and definition of tail and local positions. -Invariant 5: By the induction hypotheses, Invariant 3 (x is to appear in the new closure if and only if f = h i ).

	-Invariant 6: Lemma 2.36 (p. 27).
	The other invariants hold trivially.
	By the induction hypotheses, we get
	(b)

The essential property of CPS-convertible terms, which makes their CPS conversion immediate to perform, is the guarantee that there is no cps call outside of the tails. It makes continuations easy to represent as a series of function calls (tails) and separates them clearly from imperative blocks (heads), which are not modified by the CPC translator.

The tails are a generalisation of Definition 3.1, which will be useful for the proof of correctness of CPS-conversion. Note that x = f(e 1 , ..., e n ); return g(x, y 1 , ..., y n ) is represented by g(f (e 1 . . . e n ), y 1 . . . y n ): this translation is correct because, contrary to C, our language guarantees a left-to-right evaluation of function parameters.

Also noteworthy are the facts that:

-there is no letrec construct anymore since every function is defined at top-level, -assignments, conditions and function parameters of f are restricted to expressions, to ensure that function calls only appear in tail position, -there is no need to forbid shared variables in the parameters of g because they are ruled out of our language by design.

Early evaluation

In this section, we prove that correctness of early evaluation, ie. evaluating the expressions expr before F when reducing f (expr, . . . , expr, F ) in a tail. This result is necessary to show the correctness of the CPS-conversion, because function parameters are evaluated before any function call when building continuations.

The reduction rules may be simplified somewhat for CPS-convertible terms. We do not need to keep an explicit environment of functions since there are no inner functions any more; for the same reason, the (letrec) rule disappears. Instead, we use a constant environment F holding every function used in the reduced term M . To account for the absence of free variables, the closures in F need not carry an environment. As a result, in the (call) rule, ρ ′ = ε and F ′ = F .

Early evaluation is correct for lifted terms because a lifted term can never modify the variables that are not in its environment, since it cannot access them through closures. Lemma 3.3. Let M be a lambda-lifted term. Then,

Proof. By induction on the structure of the reduction. The key points are the use of ρ ′ = ε in the (call) case, and the absence of (letrec) rules.

(val) and (var) Trivial (s = s ′ ).

Definition 3.7 (CPS-convertible reduction rules).

when expr, σ

We do not detail the rules for → e , which simply looks for variables in σ and evaluates arithmetical and boolean operators.

Early evaluation Note that Rule 12 evaluates every function parameter in a tail before the evaluation of the tail itself. This is precisely the early evaluation process described above, which is correct by Theorem 3.5. We introduce early evaluation directly in the reduction rules rather than using it as a lemma to simplify the proof of correctess of the CPS-conversion.

CPS terms

Unlike classical CPS conversion techniques [START_REF] Plotkin | Call-by-name, call-by-value and the lambda-calculus[END_REF], our CPS terms are not continuations, but a procedure which builds and executes the continuation of a term. Construction is performed by push, which adds a function to the current continuation, and execution by invoke, which calls the first function of the continuation, optionally passing it the return value of the current function.

Definition 3.8 (CPS terms).

Continuations and reduction rules A continuation is a sequence of function calls to be performed, with already evaluated parameters. We write • for appending a function to a continuation, and ⊡ for a "hole", i.e. an unknown parameter.

Definition 3.9 (Continuations).

The reduction rules for CPS terms are isomorphic to the rules for CPS-convertible terms, except that they use continuations instead of contexts. Definition 3.10 (CPS reduction rules).

Well-formed terms Not all CPS term will lead to a correct reduction. If we push a function expecting the result of another function and invoke it immediately, the reduction blocks:

Well-formed terms avoid this behaviour. Definition 3.11 (Well-formed term). A continuation queue is well-formed if it does not end with: push f (expr, . . . , expr, ⊡) ; invoke .

A term is well-formed if every continuation queue in this term is well-formed.

Correctess of the CPS-conversion

We define the CPS conversion as a mapping from CPS-convertible terms to CPS terms.

Definition 3.12 (CPS conversion).

(Q ; f (expr, . . . , expr)) = push f (expr, . . . , expr) ; Q (Q ; f (expr, . . . , expr, F )) = push f (expr, . . . , expr, ⊡) ; (Q ; F )

In the rest of this section, we prove that this mapping yields an isomorphism between the reduction rules of CPS-convertible terms and well-formed CPS terms, whence the correctness of our CPS conversion (Theorem 3.17).

We first prove two lemmas to show that yields only well-formed CPS terms. This leads to a third lemma to show that is a bijection between CPS-convertible terms and well-formed CPS terms.

CPS-convertible terms have been carefully designed to make CPS conversion as simple as possible. Accordingly, the following three proofs, while long and tedious, are fairly trivial. Lemma 3.13. Let Q be a continuation queue. Then Q is well-formed.

Proof. By induction on the structure of a tail. Proof. Induction on the structure of T , using the above lemma.

Lemma 3.15. The relation is a bijection between CPS-convertible terms and well-formed CPS terms.

Proof. Consider the following mapping from well-formed CPS terms to CPS-convertible terms:

(push f (expr, . . . , expr) ; Q) = Q ; f (expr, . . . , expr)

The existence of Q ′ is guaranteed by well-formedness:

for every x i in dom(σ)