Closure conversion
InductiveSource values of closure conversion#✓fully proved
A source value is a closure of a raw term \(b\) (the body of a lambda) over an environment \(\rho\), which is a list of source values.
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 1 · Used by 14
InductiveBig-step semantics of the closure-conversion source#✓fully proved
Evaluation \(\rho \vdash t \Downarrow v\) of a raw term \(t\) to a source value \(v\) in an environment \(\rho\) (a list of source values, where variable \(n\) refers to the entry of \(\rho\) at index \(n\), counting from \(0\)) is the least relation closed under the following rules, a call-by-value environment semantics that ignores the type annotations of lambdas. A variable \(n\) evaluates to the entry of \(\rho\) at index \(n\), when that entry exists. A lambda \(\lambda. b\) evaluates to the closure of \(b\) over \(\rho\). If \(f\) evaluates in \(\rho\) to the closure of \(b\) over \(\rho'\), if \(\rho \vdash a \Downarrow v\), and if \(v :: \rho' \vdash b \Downarrow w\), where \(v :: \rho'\) is \(\rho'\) with \(v\) added at index \(0\), then \(\rho \vdash f\,a \Downarrow w\).
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
Uses 3 · Used by 5
TheoremSource evaluation is deterministic#✓fully proved
For every environment \(\rho\) of source values and every raw term \(t\), if \(t\) evaluates in \(\rho\) to source values \(v\) and \(w\), then \(v = w\).
theorem Eval.deterministic {ρ : List (Value Base)} {t : Stlc.RawTm Base} {v w : Value Base}
(hv : Eval ρ t v) (hw : Eval ρ t w) : v = w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:43
Uses 4
InductiveTarget terms of closure conversion#✓fully proved
The terms of the closure-conversion target language, with variables as de Bruijn indices, are: a variable \(n\) for each natural number \(n\); code \(\mathsf{code}\,b\) of one parameter, whose body \(b\) is evaluated with only its parameter in scope, as variable \(0\); application \(f\,a\) of code to an argument; the unit term \(\mathsf{unit}\) (the empty tuple); pairs \((a, b)\); the projections \(\mathsf{fst}\,e\) and \(\mathsf{snd}\,e\); and \(\mathsf{let}\ e\ \mathsf{in}\ b\), which binds the value of \(e\) as variable \(0\) in \(b\).
Cslib.Languages.LambdaCalculus.ClosureConversion.Target.Tm · 18 lines
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
| fst : Tm → Tm
/-- Second projection. -/
| snd : Tm → Tm
/-- `letIn e b` evaluates `e` and binds it as variable `0` in `b`. -/
| letIn : Tm → Tm → Tm
deriving DecidableEq, Repr
Used by 35
InductiveTarget values of closure conversion#✓fully proved
A value of the closure-conversion target language is code \(\mathsf{code}\,b\) for a target term \(b\), the unit value \(\mathsf{unit}\), or a pair \((v, w)\) of values.
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
Uses 1 · Used by 18
InductiveBig-step semantics of the closure-conversion target#✓fully proved
Evaluation \(\rho \vdash e \Downarrow v\) of a target term \(e\) to a target value \(v\) in an environment \(\rho\) (a list of values, where variable \(n\) refers to the entry of \(\rho\) at index \(n\), counting from \(0\)) is the least relation closed under the following rules. A variable \(n\) evaluates to the entry of \(\rho\) at index \(n\), when that entry exists. Code evaluates to itself: \(\rho \vdash \mathsf{code}\,b \Downarrow \mathsf{code}\,b\). If \(\rho \vdash f \Downarrow \mathsf{code}\,b\), \(\rho \vdash a \Downarrow v\) and \([v] \vdash b \Downarrow w\), then \(\rho \vdash f\,a \Downarrow w\); so a code body runs in the one-element environment \([v]\) and never sees \(\rho\). The unit term evaluates to the unit value. If \(\rho \vdash a \Downarrow v\) and \(\rho \vdash b \Downarrow w\), then \(\rho \vdash (a, b) \Downarrow (v, w)\). If \(\rho \vdash e \Downarrow (v, w)\), then \(\rho \vdash \mathsf{fst}\,e \Downarrow v\) and \(\rho \vdash \mathsf{snd}\,e \Downarrow w\). If \(\rho \vdash e \Downarrow v\) and \(v :: \rho \vdash b \Downarrow w\), where \(v :: \rho\) is \(\rho\) with \(v\) added at index \(0\), then \(\rho \vdash \mathsf{let}\ e\ \mathsf{in}\ b \Downarrow w\).
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
| letIn {ρ : List Value} {e b : Tm} {v w : Value}
(he : Eval ρ e v) (hb : Eval (v :: ρ) b w) : Eval ρ (.letIn e b) w
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
Uses 2 · Used by 14
DefinitionLifting a renaming under a binder, for the closure-conversion target#✓fully proved
The lift \(r^{\uparrow}\) of a renaming \(r : \mathbb{N} \to \mathbb{N}\) of de Bruijn indices sends \(0\) to \(0\) and \(i + 1\) to \(r(i) + 1\).
Used by 3
DefinitionRenaming target terms#✓fully proved
For \(r : \mathbb{N} \to \mathbb{N}\), the renaming \(t[r]\) of a target term \(t\) replaces each variable \(i\) by \(r(i)\), leaves code \(\mathsf{code}\,b\) unchanged (its body \(b\) is not renamed), fixes \(\mathsf{unit}\), commutes with application, pairing and the two projections, and sends \(\mathsf{let}\ e\ \mathsf{in}\ b\) to \(\mathsf{let}\ e[r]\ \mathsf{in}\ b[r^{\uparrow}]\), where \(r^{\uparrow}\), the lift of \(r\) under one binder, sends \(0\) to \(0\) and \(i + 1\) to \(r(i) + 1\).
def rename (r : Nat → Nat) : Tm → Tm
| .var i => .var (r i)
| .code b => .code b
| .app f a => .app (rename r f) (rename r a)
| .unit => .unit
| .pair a b => .pair (rename r a) (rename r b)
| .fst e => .fst (rename r e)
| .snd e => .snd (rename r e)
| .letIn e b => .letIn (rename r e) (rename (liftRen r) b)
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def liftRen (r : Nat → Nat) : Nat → Nat
| 0 => 0
| i + 1 => r i + 1
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:84
Uses 2 · Used by 3
DefinitionShifting a target term#✓fully proved
The shift of a target term \(e\) is its renaming by the successor map \(i \mapsto i + 1\): every free variable of \(e\) goes up by one, and code bodies are left unchanged.
def shift (e : Tm) : Tm := rename Nat.succ e
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def rename (r : Nat → Nat) : Tm → Tm
| .var i => .var (r i)
| .code b => .code b
| .app f a => .app (rename r f) (rename r a)
| .unit => .unit
| .pair a b => .pair (rename r a) (rename r b)
| .fst e => .fst (rename r e)
| .snd e => .snd (rename r e)
| .letIn e b => .letIn (rename r e) (rename (liftRen r) b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:90
Uses 2 · Used by 8
TheoremEvaluation is stable under renaming#✓fully proved
Let \(\rho\) and \(\rho'\) be environments and \(r : \mathbb{N} \to \mathbb{N}\) a renaming such that, for every index \(i\) and value \(w\), if \(\rho\) has entry \(w\) at index \(i\) then \(\rho'\) has entry \(w\) at index \(r(i)\). If a target term \(e\) evaluates to \(v\) in \(\rho\), then the renaming of \(e\) by \(r\) evaluates to \(v\) in \(\rho'\).
theorem Eval.rename {ρ ρ' : List Value} {e : Tm} {v : Value} (h : Eval ρ e v)
{r : Nat → Nat} (hr : ∀ i w, ρ[i]? = some w → ρ'[r i]? = some w) :
Eval ρ' (e.rename r) v
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
Uses 5 · Used by 1
TheoremEvaluation of a shifted term#✓fully proved
If a target term \(e\) evaluates to \(v\) in an environment \(\rho\), then for every value \(x\) the shift of \(e\) evaluates to \(v\) in the environment \(x :: \rho\) obtained from \(\rho\) by adding \(x\) at index \(0\).
theorem Eval.shift {ρ : List Value} {e : Tm} {v : Value} (x : Value) (h : Eval ρ e v) :
Eval (x :: ρ) e.shift v
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
Uses 5 · Used by 2
InductiveWell-scoped target terms#✓fully proved
For a natural number \(m\), a target term \(e\) is scoped in \(m\) when every free variable of \(e\) is less than \(m\) and every code body in \(e\) is closed, that is, scoped in \(1\). Inductively: a variable \(i\) is scoped in \(m\) when \(i < m\); \(\mathsf{code}\,b\) is scoped in every \(m\) when \(b\) is scoped in \(1\); \(\mathsf{unit}\) is scoped in every \(m\); an application, a pair or a projection is scoped in \(m\) when its immediate subterms are; and \(\mathsf{let}\ e\ \mathsf{in}\ b\) is scoped in \(m\) when \(e\) is scoped in \(m\) and \(b\) is scoped in \(m + 1\).
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
TheoremShifting preserves scoping#✓fully proved
If a target term \(e\) is scoped in \(m\), then its shift is scoped in \(m + 1\).
theorem Scoped.shift {m : Nat} {e : Tm} (h : Scoped m e) : Scoped (m + 1) e.shift
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:130
Uses 5 · Used by 2
DefinitionIterated second projection#✓fully proved
For a natural number \(k\) and a target term \(e\), the term \(\mathsf{snd}^k\,e\) applies the second projection \(k\) times to \(e\): \(\mathsf{snd}^0\,e = e\) and \(\mathsf{snd}^{k+1}\,e = \mathsf{snd}\,(\mathsf{snd}^k\,e)\).
def snds : Nat → Tm → Tm
| 0, e => e
| k + 1, e => .snd (snds k e)
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
Uses 1 · Used by 7
DefinitionEnvironment-packing term#✓fully proved
For a map \(\mathit{acc}\) from natural numbers to target terms and a natural number \(n\), the environment-packing term of \(\mathit{acc}\) and \(n\) is the target term \((\mathit{acc}(0), (\mathit{acc}(1), \dots (\mathit{acc}(n - 1), \mathsf{unit})\dots))\) packing \(\mathit{acc}(0), \dots, \mathit{acc}(n - 1)\) as nested pairs ending in \(\mathsf{unit}\). Recursively, it is \(\mathsf{unit}\) for \(n = 0\), and for \(n + 1\) it is the pair of \(\mathit{acc}(0)\) and the environment-packing term of \(i \mapsto \mathit{acc}(i + 1)\) and \(n\).
def envOf (acc : Nat → Tm) : Nat → Tm
| 0 => .unit
| n + 1 => .pair (acc 0) (envOf (fun i => acc (i + 1)) n)
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
Uses 1 · Used by 4
DefinitionAccessors inside converted code#✓fully proved
Write \(\#0\) for the target variable \(0\) and \(\mathsf{snd}^i\) for \(i\) applications of the second projection. The code accessor for index \(0\) is \(\mathsf{fst}\,\#0\), and the code accessor for index \(i + 1\) is \(\mathsf{fst}\,(\mathsf{snd}^i\,(\mathsf{snd}\,\#0))\). When the code parameter \(\#0\) is the pair of the argument and an environment encoded as nested pairs, accessor \(0\) fetches the argument and accessor \(i + 1\) fetches entry \(i\) of the environment.
def codeAcc : Nat → Tm
| 0 => .fst (.var 0)
| i + 1 => .fst (snds i (.snd (.var 0)))
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def snds : Nat → Tm → Tm
| 0, e => e
| k + 1, e => .snd (snds k e)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:59
Uses 2 · Used by 5
DefinitionClosure conversion with accessors#✓fully proved
Let \(\mathit{acc}\) be a family of target terms indexed by the natural numbers (accessor \(i\) fetches source variable \(i\)) and \(n\) a natural number (the number of source variables in scope). The conversion \(\mathcal{C}(\mathit{acc}, n, t)\) of a source term \(t\) is defined by recursion on \(t\). A variable \(i\) converts to \(\mathit{acc}(i)\). A lambda with body \(b\) (whatever its parameter type) converts to the pair of \(\mathsf{code}\,\mathcal{C}(c, n + 1, b)\), where \(c\) is the family of code accessors, and the target term packing \(\mathit{acc}(0), \dots, \mathit{acc}(n - 1)\) as nested pairs ending in \(\mathsf{unit}\). An application \(f\,a\) converts to \(\mathsf{let}\ \mathcal{C}(\mathit{acc}, n, f)\ \mathsf{in}\ (\mathsf{fst}\,\#0)\, (\mathcal{C}(\mathit{acc}', n, a), \mathsf{snd}\,\#0)\), where \(\#0\) is the target variable \(0\) and \(\mathit{acc}'(i)\) is the shift of \(\mathit{acc}(i)\) for every \(i\).
def convert : (Nat → Tm) → Nat → Stlc.RawTm Base → Tm
| acc, _, .var i => acc i
| acc, n, .lam _ body => .pair (.code (convert codeAcc (n + 1) body)) (envOf acc n)
| acc, n, .app f a =>
.letIn (convert acc n f)
(.app (.fst (.var 0)) (.pair (convert (fun i => (acc i).shift) n a) (.snd (.var 0))))
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def codeAcc : Nat → Tm
| 0 => .fst (.var 0)
| i + 1 => .fst (snds i (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:72
def envOf (acc : Nat → Tm) : Nat → Tm
| 0 => .unit
| n + 1 => .pair (acc 0) (envOf (fun i => acc (i + 1)) n)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:65
Uses 6 · Used by 4
DefinitionClosure conversion of a program#✓fully proved
The closure conversion of a source term \(t\) is the conversion of \(t\) in a scope of \(0\) variables with the accessors that send each index \(i\) to the target variable \(i\). It is intended for closed terms.
def closureConvert (t : Stlc.RawTm Base) : Tm :=
convert .var 0 t
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def convert : (Nat → Tm) → Nat → Stlc.RawTm Base → Tm
| acc, _, .var i => acc i
| acc, n, .lam _ body => .pair (.code (convert codeAcc (n + 1) body)) (envOf acc n)
| acc, n, .app f a =>
.letIn (convert acc n f)
(.app (.fst (.var 0)) (.pair (convert (fun i => (acc i).shift) n a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:78
Uses 3 · Used by 2
DefinitionEncoding a list of target values#✓fully proved
The encoding of a list of target values as nested pairs sends the empty list to the unit value and a list with head \(w\) and tail \(ws\) to the pair of \(w\) and the encoding of \(ws\). Thus \([w_0, \dots, w_{k-1}]\) is encoded as \((w_0, (w_1, \dots (w_{k-1}, \mathsf{unit})))\).
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
Uses 1 · Used by 10
InductiveValue relation for closure conversion#✓fully proved
The relation between source values and target values of closure conversion is the least relation such that, for every source lambda body \(b\), every list \(\rho\) of source values and every list \(ws\) of target values with \(|\rho| = |ws|\) and \(\rho_i\) related to \(ws_i\) for every \(i < |\rho|\), the source closure of \(b\) over \(\rho\) is related to the target pair \((\mathsf{code}\,c, E)\). Here \(c\) is the closure conversion of \(b\) in a scope of \(|\rho| + 1\) variables with the code accessors, which read variable \(0\) as \(\mathsf{fst}\,\#0\) and variable \(i + 1\) as \(\mathsf{fst}\,(\mathsf{snd}^i\,(\mathsf{snd}\,\#0))\), where \(\#0\) is the code parameter and \(\mathsf{snd}^i\) applies the second projection \(i\) times; and \(E\) is the encoding of \(ws\) as nested pairs ending in the unit value.
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def convert : (Nat → Tm) → Nat → Stlc.RawTm Base → Tm
| acc, _, .var i => acc i
| acc, n, .lam _ body => .pair (.code (convert codeAcc (n + 1) body)) (envOf acc n)
| acc, n, .app f a =>
.letIn (convert acc n f)
(.app (.fst (.var 0)) (.pair (convert (fun i => (acc i).shift) n a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:78
def codeAcc : Nat → Tm
| 0 => .fst (.var 0)
| i + 1 => .fst (snds i (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:72
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
DefinitionAccessors implementing a source environment#✓fully proved
Let \(\rho\) be a list of source values, \(\rho_t\) a list of target values and \(\mathit{acc}\) a family of target terms indexed by the natural numbers. The accessors \(\mathit{acc}\) implement \(\rho\) in \(\rho_t\) when, for every index \(i\) less than the length of \(\rho\), there is a target value \(w\) such that \(\mathit{acc}(i)\) evaluates to \(w\) in the environment \(\rho_t\) and the entry of \(\rho\) at index \(i\) is related to \(w\) by the value relation of closure conversion.
def AccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm) : Prop :=
∀ i (h : i < ρ.length), ∃ w, Eval ρt (acc i) w ∧ ValRel ρ[i] w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:97
TheoremPacked accessors evaluate to an encoded related environment#✓fully proved
Let \(\rho\) be a list of source values, \(\rho_t\) a list of target values and \(\mathit{acc}\) a map from natural numbers to target terms, and suppose the accessors \(\mathit{acc}\) implement \(\rho\) in \(\rho_t\): for every \(i < |\rho|\), the term \(\mathit{acc}(i)\) evaluates in \(\rho_t\) to a target value related to \(\rho_i\) by the value relation. Then there is a list \(ws\) of target values with \(|ws| = |\rho|\) and \(\rho_i\) related to \(ws_i\) for every \(i < |\rho|\), such that the target term packing \(\mathit{acc}(0), \dots, \mathit{acc}(|\rho| - 1)\) as nested pairs ending in \(\mathsf{unit}\) evaluates in \(\rho_t\) to the encoding of \(ws\) as nested pairs ending in the unit value.
theorem AccRel.envOf {ρ : List (Source.Value Base)} {ρt : List Value} {acc : Nat → Tm}
(h : AccRel ρ ρt acc) :
∃ ws : List Value, Eval ρt (ClosureConversion.envOf acc ρ.length) (encodeEnv ws) ∧
ρ.length = ws.length ∧
∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def AccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm) : Prop :=
∀ i (h : i < ρ.length), ∃ w, Eval ρt (acc i) w ∧ ValRel ρ[i] w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:105
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def envOf (acc : Nat → Tm) : Nat → Tm
| 0 => .unit
| n + 1 => .pair (acc 0) (envOf (fun i => acc (i + 1)) n)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:65
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:97
Uses 8 · Used by 1
TheoremIterated second projections of an encoded environment#✓fully proved
Let \(\rho\) be a list of target values, \(e\) a target term and \(ws = [w_0, \dots, w_{m-1}]\) a list of target values, and suppose \(e\) evaluates in \(\rho\) to the encoding of \(ws\), the nested pairs \((w_0, (w_1, \dots (w_{m-1}, \mathsf{unit})\dots))\). Then for every natural number \(k \le m\), the term obtained by applying the second projection \(k\) times to \(e\) evaluates in \(\rho\) to the encoding of \([w_k, \dots, w_{m-1}]\), the list \(ws\) with its first \(k\) entries dropped.
theorem eval_snds {ρt : List Value} {e : Tm} {ws : List Value}
(he : Eval ρt e (encodeEnv ws)) {k : Nat} (hk : k ≤ ws.length) :
Eval ρt (snds k e) (encodeEnv (ws.drop k))
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
def snds : Nat → Tm → Tm
| 0, e => e
| k + 1, e => .snd (snds k e)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:59
Uses 5 · Used by 2
TheoremCode accessors implement the extended closure environment#✓fully proved
Let \(v\) be a source value related to a target value \(w\) by the value relation of closure conversion, and let \(\rho\) and \(ws\) be lists of source and target values of the same length such that, for every index \(i\) below that length, the entry of \(\rho\) at \(i\) is related to the entry of \(ws\) at \(i\). Then the code accessors implement the source environment \(v :: \rho\) (\(\rho\) with \(v\) added at index \(0\)) in the one-element target environment whose entry is the pair of \(w\) and the encoding of \(ws\) as nested pairs ending in \(\mathsf{unit}\).
theorem accRel_codeAcc {v : Source.Value Base} {ρ : List (Source.Value Base)} {w : Value}
{ws : List Value} (hvw : ValRel v w) (hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
AccRel (v :: ρ) [.pair w (encodeEnv ws)] codeAcc
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:97
def AccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm) : Prop :=
∀ i (h : i < ρ.length), ∃ w, Eval ρt (acc i) w ∧ ValRel ρ[i] w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:105
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
def codeAcc : Nat → Tm
| 0 => .fst (.var 0)
| i + 1 => .fst (snds i (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:72
Uses 10 · Used by 1
TheoremCorrectness of closure conversion#✓fully proved
Let \(\rho\) be a list of source values, \(\ell\) its length, and \(t\) a source term that evaluates to a source value \(v\) in the environment \(\rho\). Let \(\rho_t\) be a list of target values and \(\mathit{acc}\) a family of target terms indexed by the natural numbers that implement \(\rho\) in \(\rho_t\). Then there is a target value \(w\) such that the conversion of \(t\) in a scope of \(\ell\) variables with accessors \(\mathit{acc}\) evaluates to \(w\) in the environment \(\rho_t\), and \(v\) is related to \(w\) by the value relation of closure conversion.
theorem convert_correct {ρ : List (Source.Value Base)} {t : Stlc.RawTm Base}
{v : Source.Value Base} (h : Source.Eval ρ t v) {ρt : List Value} {acc : Nat → Tm}
(hacc : AccRel ρ ρt acc) :
∃ w, Eval ρt (convert acc ρ.length t) w ∧ ValRel v w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:43
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def AccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm) : Prop :=
∀ i (h : i < ρ.length), ∃ w, Eval ρt (acc i) w ∧ ValRel ρ[i] w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:105
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def convert : (Nat → Tm) → Nat → Stlc.RawTm Base → Tm
| acc, _, .var i => acc i
| acc, n, .lam _ body => .pair (.code (convert codeAcc (n + 1) body)) (envOf acc n)
| acc, n, .app f a =>
.letIn (convert acc n f)
(.app (.fst (.var 0)) (.pair (convert (fun i => (acc i).shift) n a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:78
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:97
Uses 17 · Used by 1
TheoremCorrectness of closure conversion in the empty environment#✓fully proved
If a source term \(t\) evaluates to a source value \(v\) in the empty environment, then there is a target value \(w\) such that the closure conversion of \(t\) evaluates to \(w\) in the empty environment and \(v\) is related to \(w\) by the value relation of closure conversion.
theorem closureConvert_correct {t : Stlc.RawTm Base} {v : Source.Value Base}
(h : Source.Eval [] t v) : ∃ w, Eval [] (closureConvert t) w ∧ ValRel v w
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:43
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def closureConvert (t : Stlc.RawTm Base) : Tm :=
convert .var 0 t
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:86
inductive ValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : ρ.length = ws.length)
(hrel : ∀ i (h₁ : i < ρ.length) (h₂ : i < ws.length), ValRel ρ[i] ws[i]) :
ValRel (.clo body ρ) (.pair (.code (convert codeAcc (ρ.length + 1) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:97
TheoremConverted terms are well scoped#✓fully proved
Let \(m\) and \(n\) be natural numbers and \(t\) a source term whose list of free indices at binder depth \(n\) is empty, that is, \(t\) is scoped in \(n\) variables. If \(\mathit{acc}\) is a family of target terms indexed by the natural numbers such that \(\mathit{acc}(i)\) is scoped in \(m\) for every \(i < n\), then the conversion of \(t\) in a scope of \(n\) variables with accessors \(\mathit{acc}\) is scoped in \(m\); in particular, every code body it contains is scoped in \(1\).
theorem convert_scoped {m : Nat} (t : Stlc.RawTm Base) :
∀ {n : Nat}, Stlc.RawTm.freeIndices n t = [] →
∀ {acc : Nat → Tm}, (∀ i, i < n → Scoped m (acc i)) → Scoped m (convert acc n t)
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:130
def convert : (Nat → Tm) → Nat → Stlc.RawTm Base → Tm
| acc, _, .var i => acc i
| acc, n, .lam _ body => .pair (.code (convert codeAcc (n + 1) body)) (envOf acc n)
| acc, n, .app f a =>
.letIn (convert acc n f)
(.app (.fst (.var 0)) (.pair (convert (fun i => (acc i).shift) n a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:78
Uses 11 · Used by 1
TheoremClosure conversion of a closed term is well scoped#✓fully proved
If a source term \(t\) is closed (it has no free variables), then its closure conversion is scoped in \(0\): it has no free variables, and every code body in it is scoped in \(1\), so refers only to its parameter.
theorem closureConvert_scoped {t : Stlc.RawTm Base} (ht : t.Closed) :
Scoped 0 (closureConvert t)
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:130
def closureConvert (t : Stlc.RawTm Base) : Tm :=
convert .var 0 t
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:86
Uses 6
TheoremFree variables one binder deeper#✓fully proved
For every raw term \(t\) and natural numbers \(d\) and \(j\), \(j\) is a free index of \(t\) at binder depth \(d + 1\) if and only if \(j + 1\) is a free index of \(t\) at binder depth \(d\).
theorem mem_freeIndices_succ (t : Stlc.RawTm Base) (d j : Nat) :
j ∈ freeIndices (d + 1) t ↔ j + 1 ∈ freeIndices d t
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
Uses 3 · Used by 3
DefinitionVariables captured by a lambda#✓fully proved
For a raw term \(b\), the captured variables of \(b\) form the list of free indices of \(b\) at binder depth \(1\) with duplicates removed: the de Bruijn indices \(j\) such that variable \(j + 1\) occurs free in \(b\), that is, the free variables of the abstraction \(\lambda.\,b\), each listed once.
def captured (body : Stlc.RawTm Base) : List Nat := (freeIndices 1 body).dedup
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
Uses 2 · Used by 5
DefinitionFlat closure environment#✓fully proved
For a map \(\mathrm{acc}\) from natural numbers to target terms and a list \(i_1, \dots, i_n\) of natural numbers, the flat environment is the target term \((\mathrm{acc}(i_1), (\mathrm{acc}(i_2), \dots, (\mathrm{acc}(i_n), \mathsf{unit})\dots))\), which packs \(\mathrm{acc}(i)\) for each \(i\) in the list, in order, as nested pairs ending in \(\mathsf{unit}\); the empty list gives \(\mathsf{unit}\).
def envFlat (acc : Nat → Tm) : List Nat → Tm
| [] => .unit
| i :: is => .pair (acc i) (envFlat acc is)
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
Uses 1 · Used by 5
DefinitionAccessors inside flat code#✓fully proved
For a list \(L\) of natural numbers, the flat accessors for \(L\) assign a target term to each variable: variable \(0\) is sent to \(\mathsf{fst}\,\#0\), and variable \(j + 1\) is sent to \(\mathsf{fst}\,(\mathsf{snd}^k\,(\mathsf{snd}\,\#0))\). Here \(\#0\) is target variable \(0\), \(\mathsf{snd}^k\) applies the second projection \(k\) times, and \(k\) is the index of the first occurrence of \(j\) in \(L\), or the length of \(L\) if \(j\) does not occur in \(L\).
Inside flat code the parameter \(\#0\) is the pair of the argument and the environment, so variable \(0\) is the argument and variable \(j + 1\) is the entry of the environment at the position of \(j\) in \(L\).
def flatAcc (fvs : List Nat) : Nat → Tm
| 0 => .fst (.var 0)
| j + 1 => .fst (snds (fvs.idxOf j) (.snd (.var 0)))
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def snds : Nat → Tm → Tm
| 0, e => e
| k + 1, e => .snd (snds k e)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:59
DefinitionFlat closure conversion#✓fully proved
Given accessors \(\mathrm{acc}\), a map from natural numbers to target terms, the flat conversion \(C_{\mathrm{acc}}(t)\) of a raw term \(t\) is defined by recursion on \(t\). A variable \(i\) becomes \(\mathrm{acc}(i)\). A lambda \(\lambda.\,b\), whose parameter type is ignored, becomes the pair \((\mathsf{code}\,C_{\mathrm{acc}'}(b), e)\). Here \(i_1, \dots, i_n\) are the captured variables of \(b\), the environment \(e\) is \((\mathrm{acc}(i_1), (\mathrm{acc}(i_2), \dots, (\mathrm{acc}(i_n), \mathsf{unit})\dots))\), and \(\mathrm{acc}'\) sends \(0\) to \(\mathsf{fst}\,(\mathsf{var}\,0)\) and \(j + 1\) to \(\mathsf{fst}\,(\mathsf{snd}^{k+1}\,(\mathsf{var}\,0))\), where \(k\) is the position of \(j\) in that list, counting from \(0\) (the length \(n\) if \(j\) does not occur). An application \(f\,a\) becomes \(\mathsf{let}\ C_{\mathrm{acc}}(f)\ \mathsf{in}\ (\mathsf{fst}\,(\mathsf{var}\,0))\, (C_{\mathrm{acc}^{+}}(a), \mathsf{snd}\,(\mathsf{var}\,0))\), where \(\mathsf{var}\,0\) is the variable bound by the \(\mathsf{let}\) and \(\mathrm{acc}^{+}(i)\) is the shift of \(\mathrm{acc}(i)\).
def convertFlat : (Nat → Tm) → Stlc.RawTm Base → Tm
| acc, .var i => acc i
| acc, .lam _ body =>
.pair (.code (convertFlat (flatAcc (captured body)) body)) (envFlat acc (captured body))
| acc, .app f a =>
.letIn (convertFlat acc f)
(.app (.fst (.var 0)) (.pair (convertFlat (fun i => (acc i).shift) a) (.snd (.var 0))))
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def flatAcc (fvs : List Nat) : Nat → Tm
| 0 => .fst (.var 0)
| j + 1 => .fst (snds (fvs.idxOf j) (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:86
def captured (body : Stlc.RawTm Base) : List Nat := (freeIndices 1 body).dedup
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:73
def envFlat (acc : Nat → Tm) : List Nat → Tm
| [] => .unit
| i :: is => .pair (acc i) (envFlat acc is)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:80
Uses 7 · Used by 4
DefinitionFlat closure conversion of a program#✓fully proved
The flat closure conversion of a raw term \(t\) is the flat conversion of \(t\) with the accessors \(i \mapsto \mathsf{var}\,i\), which send each free variable \(i\) of \(t\) to the target variable \(i\). It is meant for closed terms.
def closureConvertFlat (t : Stlc.RawTm Base) : Tm := convertFlat .var t
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def convertFlat : (Nat → Tm) → Stlc.RawTm Base → Tm
| acc, .var i => acc i
| acc, .lam _ body =>
.pair (.code (convertFlat (flatAcc (captured body)) body)) (envFlat acc (captured body))
| acc, .app f a =>
.letIn (convertFlat acc f)
(.app (.fst (.var 0)) (.pair (convertFlat (fun i => (acc i).shift) a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:91
Uses 3 · Used by 2
InductiveFlat value relation#✓fully proved
The flat value relation between source values and target values is the least relation with the following property. Let \(b\) be a raw term, \(\rho\) a list of source values of length \(|\rho|\), \(c = (c_0, \dots, c_{m-1})\) the list of variables captured by \(\lambda. b\), and \(w_0, \dots, w_{m-1}\) target values, as many as there are captured variables. If, for every \(k < m\), \(c_k < |\rho|\) and the entry of \(\rho\) at index \(c_k\) (counting from \(0\)) is related to \(w_k\), then the source closure of \(b\) over \(\rho\) is related to the target value \((\mathsf{code}\,B, \mathrm{enc}(w_0, \dots, w_{m-1}))\), where \(B\) is the flat closure conversion of \(b\) with the flat accessors for \(c\), and \(\mathrm{enc}\) encodes a list of target values as nested pairs ending in \(\mathsf{unit}\).
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def captured (body : Stlc.RawTm Base) : List Nat := (freeIndices 1 body).dedup
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:73
def convertFlat : (Nat → Tm) → Stlc.RawTm Base → Tm
| acc, .var i => acc i
| acc, .lam _ body =>
.pair (.code (convertFlat (flatAcc (captured body)) body)) (envFlat acc (captured body))
| acc, .app f a =>
.letIn (convertFlat acc f)
(.app (.fst (.var 0)) (.pair (convertFlat (fun i => (acc i).shift) a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:91
def flatAcc (fvs : List Nat) : Nat → Tm
| 0 => .fst (.var 0)
| j + 1 => .fst (snds (fvs.idxOf j) (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:86
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
DefinitionAccessors implementing the free variables of a term#✓fully proved
Let \(\rho\) be a list of source values of length \(|\rho|\), \(\rho_t\) a list of target values, \(\mathrm{acc}\) a map assigning a target term to each natural number, and \(t\) a raw term. The accessors \(\mathrm{acc}\) implement \(t\) for \(\rho\) in \(\rho_t\) when, for every free variable \(i\) of \(t\), \(i < |\rho|\) and \(\mathrm{acc}(i)\) evaluates in the target environment \(\rho_t\) to a target value that is related, by the flat value relation, to the entry of \(\rho\) at index \(i\) (counting from \(0\)).
def FlatAccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm)
(t : Stlc.RawTm Base) : Prop :=
∀ i ∈ freeIndices 0 t, ∃ h : i < ρ.length, ∃ w, Eval ρt (acc i) w ∧ FlatValRel ρ[i] w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:105
TheoremEvaluating a flat environment#✓fully proved
Let \(\rho\) be a source environment, \(\rho_t\) a target environment, \(\mathrm{acc}\) a map from natural numbers to target terms, and \(i_1, \dots, i_n\) a list of natural numbers. Write \(\rho_i\) for the entry of \(\rho\) at index \(i\), counting from \(0\). Suppose every \(i\) in the list is less than the length of \(\rho\) and \(\mathrm{acc}(i)\) evaluates in \(\rho_t\) to a target value related to \(\rho_i\) by the flat value relation. Then there are target values \(w_1, \dots, w_n\) such that the flat environment \((\mathrm{acc}(i_1), (\dots, (\mathrm{acc}(i_n), \mathsf{unit})\dots))\) evaluates in \(\rho_t\) to \((w_1, (\dots, (w_n, \mathsf{unit})\dots))\), and for each \(k\) the index \(i_k\) is less than the length of \(\rho\) and \(w_k\) is related to \(\rho_{i_k}\) by the flat value relation.
theorem eval_envFlat {ρ : List (Source.Value Base)} {ρt : List Value} {acc : Nat → Tm} :
∀ (is : List Nat), (∀ i ∈ is, ∃ h : i < ρ.length, ∃ w, Eval ρt (acc i) w ∧
FlatValRel ρ[i] w) →
∃ ws : List Value, Eval ρt (envFlat acc is) (encodeEnv ws) ∧ is.length = ws.length ∧
∃ hbound : ∀ k (h₁ : k < is.length), is[k] < ρ.length,
∀ k (h₁ : k < is.length) (h₂ : k < ws.length), FlatValRel (ρ[is[k]]'(hbound k h₁)) ws[k]
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:105
def envFlat (acc : Nat → Tm) : List Nat → Tm
| [] => .unit
| i :: is => .pair (acc i) (envFlat acc is)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:80
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
TheoremLength of an evaluated flat environment#✓fully proved
Let \(\mathrm{acc}\) be a map from natural numbers to target terms and \(i_1, \dots, i_n\) a list of natural numbers. If the flat environment \((\mathrm{acc}(i_1), (\dots, (\mathrm{acc}(i_n), \mathsf{unit})\dots))\) evaluates in some target environment to the encoding \((w_1, (\dots, (w_k, \mathsf{unit})\dots))\) of a list of target values \(w_1, \dots, w_k\), then \(k = n\).
theorem envFlat_length {ρt : List Value} {acc : Nat → Tm}
{is : List Nat} {ws : List Value} (h : Eval ρt (envFlat acc is) (encodeEnv ws)) :
ws.length = is.length
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def envFlat (acc : Nat → Tm) : List Nat → Tm
| [] => .unit
| i :: is => .pair (acc i) (envFlat acc is)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:80
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
TheoremFlat accessors implement the variables of a closure body#✓fully proved
Let \(b\) be a raw term, let \(c = (c_0, \dots, c_{m-1})\) be the list of variables captured by \(\lambda. b\), let \(\rho\) be a list of source values of length \(|\rho|\), write \(\rho_n\) for the entry of \(\rho\) at index \(n\) (counting from \(0\)), and let \(w_0, \dots, w_{m-1}\) be target values such that \(c_k < |\rho|\) and \(\rho_{c_k}\) is related to \(w_k\) by the flat value relation for every \(k < m\). If a source value \(v\) is related to a target value \(w\) by the flat value relation, then the flat accessors for \(c\) implement the free variables of \(b\) for the source environment \(v :: \rho\) (the list \(\rho\) with \(v\) added at index \(0\)) in the one-entry target environment \([(w, \mathrm{enc}(w_0, \dots, w_{m-1}))]\), where \(\mathrm{enc}\) encodes a list of target values as nested pairs ending in \(\mathsf{unit}\). That is, for every free variable \(i\) of \(b\), \(i < |\rho| + 1\) and the flat accessor for \(i\) evaluates in that target environment to a target value related to the entry of \(v :: \rho\) at index \(i\) by the flat value relation.
theorem flatAccRel_flatAcc {v : Source.Value Base} {ρ : List (Source.Value Base)}
{body : Stlc.RawTm Base} {w : Value} {ws : List Value} (hvw : FlatValRel v w)
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatAccRel (v :: ρ) [.pair w (encodeEnv ws)] (flatAcc (captured body)) body
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:105
def captured (body : Stlc.RawTm Base) : List Nat := (freeIndices 1 body).dedup
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:73
def FlatAccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm)
(t : Stlc.RawTm Base) : Prop :=
∀ i ∈ freeIndices 0 t, ∃ h : i < ρ.length, ∃ w, Eval ρt (acc i) w ∧ FlatValRel ρ[i] w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:115
def encodeEnv : List Value → Value
| [] => .unit
| w :: ws => .pair w (encodeEnv ws)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Correctness.lean:90
def flatAcc (fvs : List Nat) : Nat → Tm
| 0 => .fst (.var 0)
| j + 1 => .fst (snds (fvs.idxOf j) (.snd (.var 0)))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:86
Uses 14 · Used by 1
TheoremCorrectness of flat closure conversion#✓fully proved
Let \(\rho\) be a source environment, \(\rho_t\) a target environment, \(\mathrm{acc}\) a map from natural numbers to target terms, and \(t\) a raw term that evaluates to a source value \(v\) in \(\rho\). Suppose that for every free variable \(i\) of \(t\), \(i\) is less than the length of \(\rho\) and \(\mathrm{acc}(i)\) evaluates in \(\rho_t\) to a target value related by the flat value relation to the entry \(\rho_i\) of \(\rho\) at index \(i\) (counting from \(0\)). Then the flat conversion of \(t\) with accessors \(\mathrm{acc}\) evaluates in \(\rho_t\) to some target value related to \(v\) by the flat value relation.
theorem convertFlat_correct {ρ : List (Source.Value Base)} {t : Stlc.RawTm Base}
{v : Source.Value Base} (h : Source.Eval ρ t v) {ρt : List Value} {acc : Nat → Tm}
(hacc : FlatAccRel ρ ρt acc t) :
∃ w, Eval ρt (convertFlat acc t) w ∧ FlatValRel v w
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:43
inductive Value where
| code : Tm → Value
| unit : Value
| pair : Value → Value → Value
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:59
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def FlatAccRel (ρ : List (Source.Value Base)) (ρt : List Value) (acc : Nat → Tm)
(t : Stlc.RawTm Base) : Prop :=
∀ i ∈ freeIndices 0 t, ∃ h : i < ρ.length, ∃ w, Eval ρt (acc i) w ∧ FlatValRel ρ[i] w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:115
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def convertFlat : (Nat → Tm) → Stlc.RawTm Base → Tm
| acc, .var i => acc i
| acc, .lam _ body =>
.pair (.code (convertFlat (flatAcc (captured body)) body)) (envFlat acc (captured body))
| acc, .app f a =>
.letIn (convertFlat acc f)
(.app (.fst (.var 0)) (.pair (convertFlat (fun i => (acc i).shift) a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:91
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:105
Uses 20 · Used by 1
TheoremCorrectness of flat closure conversion for closed programs#✓fully proved
Let \(t\) be a closed raw term, that is, one with no free variables. If \(t\) evaluates to a source value \(v\) in the empty environment, then the flat closure conversion of \(t\) evaluates in the empty target environment to some target value \(w\) related to \(v\) by the flat value relation.
theorem closureConvertFlat_correct {t : Stlc.RawTm Base} {v : Source.Value Base}
(ht : t.Closed) (h : Source.Eval [] t v) :
∃ w, Eval [] (closureConvertFlat t) w ∧ FlatValRel v w
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Value (Base : Type u) where
| clo : Stlc.RawTm Base → List (Value Base) → Value Base
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:38
inductive Eval : List (Value Base) → Stlc.RawTm Base → Value Base → Prop
| var {ρ : List (Value Base)} {n : Nat} {v : Value Base} (h : ρ[n]? = some v) :
Eval ρ (.var n) v
| lam {ρ : List (Value Base)} {A : Stlc.Ty Base} {body : Stlc.RawTm Base} :
Eval ρ (.lam A body) (.clo body ρ)
| app {ρ ρ' : List (Value Base)} {f a body : Stlc.RawTm Base} {v w : Value Base}
(hf : Eval ρ f (.clo body ρ')) (ha : Eval ρ a v) (hbody : Eval (v :: ρ') body w) :
Eval ρ (.app f a) w
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Source.lean:43
inductive Eval : List Value → Tm → Value → Prop
| var {ρ : List Value} {n : Nat} {v : Value} (h : ρ[n]? = some v) : Eval ρ (.var n) v
| code {ρ : List Value} {b : Tm} : Eval ρ (.code b) (.code b)
| app {ρ : List Value} {f a b : Tm} {v w : Value}
(hf : Eval ρ f (.code b)) (ha : Eval ρ a v) (hb : Eval [v] b w) : Eval ρ (.app f a) w
| unit {ρ : List Value} : Eval ρ .unit .unit
| pair {ρ : List Value} {a b : Tm} {v w : Value}
(ha : Eval ρ a v) (hb : Eval ρ b w) : Eval ρ (.pair a b) (.pair v w)
| fst {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.fst e) v
| snd {ρ : List Value} {e : Tm} {v w : Value}
(h : Eval ρ e (.pair v w)) : Eval ρ (.snd e) w
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:68
def closureConvertFlat (t : Stlc.RawTm Base) : Tm := convertFlat .var t
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:100
inductive FlatValRel : Source.Value Base → Value → Prop
| clo {body : Stlc.RawTm Base} {ρ : List (Source.Value Base)} {ws : List Value}
(hlen : (captured body).length = ws.length)
(hbound : ∀ k (h₁ : k < (captured body).length), (captured body)[k] < ρ.length)
(hrel : ∀ k (h₁ : k < (captured body).length) (h₂ : k < ws.length),
FlatValRel (ρ[(captured body)[k]]'(hbound k h₁)) ws[k]) :
FlatValRel (.clo body ρ)
(.pair (.code (convertFlat (flatAcc (captured body)) body)) (encodeEnv ws))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:105
Uses 11
TheoremFlat closure conversion preserves scoping#✓fully proved
Let \(t\) be a raw term, \(m\) a natural number and \(\mathrm{acc}\) a map from natural numbers to target terms. If \(\mathrm{acc}(i)\) is scoped in \(m\) for every free variable \(i\) of \(t\), then the flat conversion of \(t\) with accessors \(\mathrm{acc}\) is scoped in \(m\). In particular every code body it contains is scoped in \(1\), so refers only to its parameter.
theorem convertFlat_scoped {m : Nat} (t : Stlc.RawTm Base) {acc : Nat → Tm}
(hacc : ∀ i ∈ freeIndices 0 t, Scoped m (acc i)) : Scoped m (convertFlat acc t)
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Tm where
/-- A de Bruijn variable. -/
| var : Nat → Tm
/-- Closed code of one parameter; the body sees only variable `0`. -/
| code : Tm → Tm
/-- Call code with an argument. -/
| app : Tm → Tm → Tm
/-- The empty tuple. -/
| unit : Tm
/-- Pairing. -/
| pair : Tm → Tm → Tm
/-- First projection. -/
⋯
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:39
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:130
def convertFlat : (Nat → Tm) → Stlc.RawTm Base → Tm
| acc, .var i => acc i
| acc, .lam _ body =>
.pair (.code (convertFlat (flatAcc (captured body)) body)) (envFlat acc (captured body))
| acc, .app f a =>
.letIn (convertFlat acc f)
(.app (.fst (.var 0)) (.pair (convertFlat (fun i => (acc i).shift) a) (.snd (.var 0))))
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:91
Uses 13 · Used by 1
TheoremFlat closure conversion of a closed term is well scoped#✓fully proved
If a raw term \(t\) is closed, then its flat closure conversion is scoped in \(0\): it has no free variables, and every code body in it is scoped in \(1\), so refers only to its parameter.
theorem closureConvertFlat_scoped {t : Stlc.RawTm Base} (ht : t.Closed) :
Scoped 0 (closureConvertFlat t)
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Scoped : Nat → Tm → Prop
| var {m i : Nat} (h : i < m) : Scoped m (.var i)
| code {m : Nat} {b : Tm} (hb : Scoped 1 b) : Scoped m (.code b)
| app {m : Nat} {f a : Tm} (hf : Scoped m f) (ha : Scoped m a) : Scoped m (.app f a)
| unit {m : Nat} : Scoped m .unit
| pair {m : Nat} {a b : Tm} (ha : Scoped m a) (hb : Scoped m b) : Scoped m (.pair a b)
| fst {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.fst e)
| snd {m : Nat} {e : Tm} (h : Scoped m e) : Scoped m (.snd e)
| letIn {m : Nat} {e b : Tm} (he : Scoped m e) (hb : Scoped (m + 1) b) :
Scoped m (.letIn e b)
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Target.lean:130
def closureConvertFlat (t : Stlc.RawTm Base) : Tm := convertFlat .var t
CSLibExt/Languages/LambdaCalculus/ClosureConversion/Flat.lean:100
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.