Heap semantics of IMP
AbbreviationHeap#✓fully proved
A heap is a finite partial map from addresses to values, where addresses and values are natural numbers: it stores a value \(v \in \mathbb{N}\) at each address of a finite set of addresses in \(\mathbb{N}\), called the addresses allocated in the heap.
Used by 44
DefinitionDisjoint heaps#✓fully proved
Two heaps \(h_1\) and \(h_2\) are disjoint when no address is allocated in both: every address allocated in \(h_1\) is not allocated in \(h_2\).
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
Uses 1 · Used by 13
TheoremSymmetry of heap disjointness#✓fully proved
For heaps \(h_1\) and \(h_2\), if \(h_1\) and \(h_2\) are disjoint, then \(h_2\) and \(h_1\) are disjoint.
@[symm]
theorem Disjoint.symm {h₁ h₂ : Heap} (h : Disjoint h₁ h₂) : Disjoint h₂ h₁
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2 · Used by 1
TheoremThe empty heap is disjoint from every heap#✓fully proved
For every heap \(h\), the empty heap is disjoint from \(h\) (with the empty heap as the first heap).
theorem disjoint_empty_left (h : Heap) : Disjoint ∅ h
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2
TheoremEvery heap is disjoint from the empty heap#✓fully proved
For every heap \(h\), \(h\) is disjoint from the empty heap (with the empty heap as the second heap).
theorem disjoint_empty_right (h : Heap) : Disjoint h ∅
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2
TheoremErasing an address that the right heap of a union lacks#✓fully proved
For heaps \(h_1\) and \(h_2\), let \(h_1 \cup h_2\) be their left-biased union (at an address allocated in both it keeps the value from \(h_1\)). If the address \(a\) is not allocated in \(h_2\), then erasing \(a\) from \(h_1 \cup h_2\) gives the union of \(h_2\) with the heap obtained from \(h_1\) by erasing \(a\), taken with that heap on the left.
theorem erase_union_of_notMem {a : Nat} {h₁ h₂ : Heap} (ha : a ∉ h₂) :
Finmap.erase a (h₁ ∪ h₂) = Finmap.erase a h₁ ∪ h₂
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
Uses 1 · Used by 1
TheoremInserting an address the other heap lacks preserves disjointness#✓fully proved
If heaps \(h_1\) and \(h_2\) are disjoint and the address \(a\) is not allocated in \(h_2\), then for every value \(v\), the heap obtained from \(h_1\) by inserting \(a\) with value \(v\) (overwriting any value \(h_1\) stores at \(a\)) is disjoint from \(h_2\).
theorem disjoint_insert_left {h₁ h₂ : Heap} {a v : Nat}
(hd : Disjoint h₁ h₂) (ha : a ∉ h₂) : Disjoint (Finmap.insert a v h₁) h₂
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2 · Used by 1
TheoremErasing an address preserves disjointness#✓fully proved
If heaps \(h_1\) and \(h_2\) are disjoint, then for every address \(a\), the heap obtained from \(h_1\) by erasing \(a\) (removing the address \(a\) and its value) is disjoint from \(h_2\).
theorem disjoint_erase_left {h₁ h₂ : Heap} {a : Nat}
(hd : Disjoint h₁ h₂) : Disjoint (Finmap.erase a h₁) h₂
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2 · Used by 1
TheoremDisjointness from a singleton heap#✓fully proved
For every address \(a\), value \(v\) and heap \(h\), the singleton heap that stores \(v\) at \(a\) and allocates no other address is disjoint from \(h\) if and only if \(a\) is not allocated in \(h\).
theorem disjoint_singleton_left {a v : Nat} {h : Heap} :
Disjoint (Finmap.singleton a v) h ↔ a ∉ h
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
Uses 2
TheoremReinserting an erased value restores the heap#✓fully proved
If a heap \(h\) stores the value \(v\) at the address \(a\), then erasing \(a\) from \(h\) and then inserting \(a\) with value \(v\) gives back \(h\).
theorem insert_erase_eq_self {h : Heap} {a v : Nat} (hv : h.lookup a = some v) :
Finmap.insert a v (Finmap.erase a h) = h
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
Uses 1
TheoremEvery heap has a free address#✓fully proved
For every heap \(h\) there is an address that is not allocated in \(h\).
theorem exists_notMem (h : Heap) : ∃ a, a ∉ h
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
Uses 1 · Used by 1
InductiveHeap commands#✓fully proved
Heap commands extend the commands of IMP with heap operations. A heap command is one of: \(\mathbf{skip}\); an assignment \(x := a\); a sequence \(c_1; c_2\); a conditional \(\mathbf{if}\ b\ \mathbf{then}\ c_1\ \mathbf{else}\ c_2\); a loop \(\mathbf{while}\ b\ \mathbf{do}\ c\); a heap read \(x := [a]\); a heap write \([a] := e\); an allocation \(x := \mathbf{alloc}(e)\); or a deallocation \(\mathbf{free}(a)\). Here \(x\) is a variable (a natural number), \(a\) and \(e\) are arithmetic expressions, \(b\) is a Boolean expression, and \(c\), \(c_1\), \(c_2\) are heap commands.
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
inductive AExp where
| const (value : Nat)
| var (name : Nat)
| add (left right : AExp)
| sub (left right : AExp)
| mul (left right : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:37
inductive BExp where
| truth (value : Bool)
| eq (left right : AExp)
| le (left right : AExp)
| not (body : BExp)
| and (left right : BExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:46
Uses 2 · Used by 24
AbbreviationHeap configurations#✓fully proved
A heap configuration is a triple \((c, s, h)\) of a heap command \(c\), a store \(s\) and a heap \(h\).
abbrev HConfig := HeapCmd × State × Heap
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
Uses 3 · Used by 18
InductiveSmall-step semantics of heap commands#✓fully proved
The single-step relation \((c, s, h) \to (c', s', h')\) on heap configurations is the least relation closed under the rules below. Here \(a(s)\) is the value of an expression \(a\) in the store \(s\), \(s[x \mapsto n]\) is \(s\) with variable \(x\) set to \(n\), \(h[\ell \mapsto n]\) is \(h\) with address \(\ell\) set to \(n\), and \(h \setminus \ell\) is \(h\) with address \(\ell\) removed.
- Assignment: \((x := a, s, h) \to (\mathbf{skip}, s[x \mapsto a(s)], h)\).
- Sequence: \((\mathbf{skip}; c_2, s, h) \to (c_2, s, h)\), and if \((c_1, s, h) \to (c_1', s', h')\) then \((c_1; c_2, s, h) \to (c_1'; c_2, s', h')\).
- Conditional: \((\mathbf{if}\ b\ \mathbf{then}\ c_1\ \mathbf{else}\ c_2, s, h)\) steps to \((c_1, s, h)\) if \(b(s)\) is true and to \((c_2, s, h)\) if \(b(s)\) is false.
- Loop: \((\mathbf{while}\ b\ \mathbf{do}\ c, s, h)\) steps to \((\mathbf{if}\ b\ \mathbf{then}\ d\ \mathbf{else}\ \mathbf{skip}, s, h)\), where \(d\) is the sequence \(c; \mathbf{while}\ b\ \mathbf{do}\ c\).
- Read: if \(h\) maps the address \(a(s)\) to \(v\), then \((x := [a], s, h) \to (\mathbf{skip}, s[x \mapsto v], h)\).
- Write: if \(a(s)\) is allocated in \(h\), then \(([a] := e, s, h) \to (\mathbf{skip}, s, h[a(s) \mapsto e(s)])\).
- Allocation: for every address \(\ell\) not allocated in \(h\), \((x := \mathbf{alloc}(e), s, h) \to (\mathbf{skip}, s[x \mapsto \ell], h[\ell \mapsto e(s)])\).
- Deallocation: if \(a(s)\) is allocated in \(h\), then \((\mathbf{free}(a), s, h) \to (\mathbf{skip}, s, h \setminus a(s))\).
Cslib.IMP.HStep · 35 lines
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
| iteFalse {guard thenBranch elseBranch state heap}
(guardFalse : guard.eval state = false) :
HStep (.ite guard thenBranch elseBranch, state, heap) (elseBranch, state, heap)
| whileStep (guard) (body) (state) (heap) :
HStep (.while guard body, state, heap)
(.ite guard (.seq body (.while guard body)) .skip, state, heap)
| read {name addr state heap value}
(lookup : heap.lookup (addr.eval state) = some value) :
HStep (.read name addr, state, heap)
(.skip, Function.update state name value, heap)
| write {addr value state heap}
(mem : addr.eval state ∈ heap) :
HStep (.write addr value, state, heap)
(.skip, state, Finmap.insert (addr.eval state) (value.eval state) heap)
| alloc {name value state heap address}
(notMem : address ∉ heap) :
HStep (.alloc name value, state, heap)
(.skip, Function.update state name address,
Finmap.insert address (value.eval state) heap)
| free {addr state heap}
(mem : addr.eval state ∈ heap) :
HStep (.free addr, state, heap)
(.skip, state, Finmap.erase (addr.eval state) heap)
abbrev HConfig := HeapCmd × State × Heap
CSLibExt/Languages/IMP/HeapStep.lean:53
Uses 8 · Used by 17
AbbreviationMulti-step heap execution#✓fully proved
The relation \((c, s, h) \to^* (c', s', h')\) on heap configurations is the reflexive-transitive closure of the small-step relation: it holds when the first configuration reaches the second by a finite, possibly empty, sequence of small steps.
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
abbrev HConfig := HeapCmd × State × Heap
CSLibExt/Languages/IMP/HeapStep.lean:53
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 2 · Used by 15
DefinitionSafe heap configurations#✓fully proved
A heap configuration, consisting of a heap command, a store and a heap, is safe when every heap configuration reachable from it in zero or more heap steps either has command \(\mathtt{skip}\) or can take a further heap step.
def Safe (cfg : HConfig) : Prop :=
∀ cfg', HSteps cfg cfg' → cfg'.1 = .skip ∨ ∃ cfg'', HStep cfg' cfg''
abbrev HConfig := HeapCmd × State × Heap
CSLibExt/Languages/IMP/HeapStep.lean:53
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 6 · Used by 10
TheoremSafety is preserved along executions#✓fully proved
If a heap configuration is safe and reaches a second configuration by finitely many (possibly zero) small steps, then the second configuration is safe.
theorem Safe.of_steps {cfg cfg' : HConfig} (hsafe : Safe cfg)
(hsteps : HSteps cfg cfg') : Safe cfg'
abbrev HConfig := HeapCmd × State × Heap
CSLibExt/Languages/IMP/HeapStep.lean:53
def Safe (cfg : HConfig) : Prop :=
∀ cfg', HSteps cfg cfg' → cfg'.1 = .skip ∨ ∃ cfg'', HStep cfg' cfg''
CSLibExt/Languages/IMP/HeapStep.lean:97
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
Uses 4 · Used by 1
TheoremAdding a frame heap preserves the ability to step#✓fully proved
Let \(h\) and \(h_f\) be disjoint heaps, \(c\) a heap command and \(s\) a store. If the configuration \((c, s, h)\) can take a small step, then so can \((c, s, h \cup h_f)\).
Allocation may choose a different fresh address on the larger heap.
theorem exists_step_frame {c : HeapCmd} {s : State} {h hf : Heap}
(_hd : Heap.Disjoint h hf) (hex : ∃ cfg', HStep (c, s, h) cfg') :
∃ cfg', HStep (c, s, h ∪ hf) cfg'
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 11 · Used by 1
TheoremFrame decomposition of a single heap step#✓fully proved
Let \(h\) and \(h_f\) be disjoint heaps, \(c\) a heap command and \(s\) a store, and suppose that the configuration \((c, s, h)\) can take a small step. If \((c, s, h \cup h_f)\) takes a small step to \((c', s', h'')\), then there is a heap \(h_1\), disjoint from \(h_f\), such that \((c, s, h)\) takes a small step to \((c', s', h_1)\) and \(h'' = h_1 \cup h_f\).
The step-existence hypothesis forces any address the step touches to lie in \(h\).
theorem decompose_of_safe_step {c c' : HeapCmd} {s s' : State} {h hf h'' : Heap}
(hd : Heap.Disjoint h hf) (hex : ∃ cfg', HStep (c, s, h) cfg')
(hstep : HStep (c, s, h ∪ hf) (c', s', h'')) :
∃ h₁, HStep (c, s, h) (c', s', h₁) ∧ Heap.Disjoint h₁ hf ∧ h'' = h₁ ∪ hf
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 13 · Used by 1
TheoremFrame decomposition of heap executions#✓fully proved
Let \(h\) and \(h_f\) be disjoint heaps, \(c\) a heap command and \(s\) a store, and suppose that the configuration \((c, s, h)\) is safe. If \((c, s, h \cup h_f)\) reaches \((c'', s'', h'')\) by finitely many (possibly zero) small steps, then there is a heap \(h_2\), disjoint from \(h_f\), such that \((c, s, h)\) reaches \((c'', s'', h_2)\) by finitely many small steps, \(h'' = h_2 \cup h_f\), and \((c'', s'', h_2)\) is safe.
Safety supplies the step-existence that single-step decomposition needs at each stage.
theorem decompose_of_safe {c c'' : HeapCmd} {s s'' : State} {h hf h'' : Heap}
(hd : Heap.Disjoint h hf) (hsafe : Safe (c, s, h))
(hsteps : HSteps (c, s, h ∪ hf) (c'', s'', h'')) :
∃ h₂, HSteps (c, s, h) (c'', s'', h₂) ∧ Heap.Disjoint h₂ hf ∧
h'' = h₂ ∪ hf ∧ Safe (c'', s'', h₂)
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Disjoint (h₁ h₂ : Heap) : Prop := ∀ a, a ∈ h₁ → a ∉ h₂
CSLibExt/Languages/IMP/Heap.lean:40
def Safe (cfg : HConfig) : Prop :=
∀ cfg', HSteps cfg cfg' → cfg'.1 = .skip ∨ ∃ cfg'', HStep cfg' cfg''
CSLibExt/Languages/IMP/HeapStep.lean:97
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
Uses 14 · Used by 1
DefinitionEmbedding of IMP into the heap language#✓fully proved
The embedding sends each plain IMP command to the heap command of the same shape: \(\mathtt{skip}\) goes to \(\mathtt{skip}\), an assignment of an arithmetic expression to a variable goes to the same assignment, a sequence goes to the sequence of the embeddings of its parts, and a conditional or while loop goes to the conditional or while loop with the same guard and with each subcommand replaced by its embedding.
def toHeap : Cmd → HeapCmd
| .skip => .skip
| .assign name value => .assign name value
| .seq first second => .seq first.toHeap second.toHeap
| .ite guard thenBranch elseBranch =>
.ite guard thenBranch.toHeap elseBranch.toHeap
| .while guard body => .while guard body.toHeap
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
Uses 4 · Used by 7
TheoremHeap steps of embedded commands are plain steps#✓fully proved
Let \(c\) be a plain IMP command, \(s\) a store and \(h\) a heap, and write \(\overline{d}\) for the embedding of a plain command \(d\) into the heap language. Then \((\overline{c}, s, h)\) takes a heap step to a heap configuration \(K\) if and only if there are a plain command \(c'\) and a store \(s'\) such that \((c, s)\) takes a plain small step to \((c', s')\) and \(K = (\overline{c'}, s', h)\).
theorem toHeap_iff {c : Cmd} {s : State} {h : Heap} {cfg : HConfig} :
HStep (c.toHeap, s, h) cfg ↔
∃ c' s', Step (c, s) (c', s') ∧ cfg = (c'.toHeap, s', h)
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
abbrev HConfig := HeapCmd × State × Heap
CSLibExt/Languages/IMP/HeapStep.lean:53
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
inductive Step : Config → Config → Prop
| assign (state) (name) (value) :
Step (.assign name value, state)
(.skip, Function.update state name (value.eval state))
| seqSkip (second) (state) :
Step (.seq .skip second, state) (second, state)
| seqStep {first first' second initial final}
(step : Step (first, initial) (first', final)) :
Step (.seq first second, initial) (.seq first' second, final)
| iteTrue {guard thenBranch elseBranch state}
(guardTrue : guard.eval state = true) :
Step (.ite guard thenBranch elseBranch, state) (thenBranch, state)
⋯
CSLibExt/Languages/IMP/SmallStep.lean:35
Uses 13 · Used by 3
TheoremExecutions of embedded commands are plain executions#✓fully proved
Let \(c\) be a plain IMP command, \(s\) a store and \(h\) a heap, and write \(\overline{d}\) for the embedding of a plain command \(d\) into the heap language. If \((\overline{c}, s, h)\) reaches a heap configuration \((c_2, s_2, h_2)\) in zero or more heap steps, then \(h_2 = h\) and there is a plain command \(c_2'\) with \(c_2 = \overline{c_2'}\) such that \((c, s)\) reaches \((c_2', s_2)\) in zero or more plain small steps.
theorem of_toHeap {c : Cmd} {s : State} {h : Heap} {c₂ : HeapCmd} {s₂ : State}
{h₂ : Heap} (hsteps : HSteps (c.toHeap, s, h) (c₂, s₂, h₂)) :
∃ c₂', c₂ = c₂'.toHeap ∧ Steps (c, s) (c₂', s₂) ∧ h₂ = h
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
abbrev Steps : Config → Config → Prop := Relation.ReflTransGen Step
CSLibExt/Languages/IMP/SmallStep.lean:55
Uses 12 · Used by 3
TheoremPlain executions lift to the heap language#✓fully proved
Let \(c, c_2\) be plain IMP commands, \(s, s_2\) stores and \(h\) a heap, and write \(\overline{d}\) for the embedding of a plain command \(d\) into the heap language. If \((c, s)\) reaches \((c_2, s_2)\) in zero or more plain small steps, then \((\overline{c}, s, h)\) reaches \((\overline{c_2}, s_2, h)\) in zero or more heap steps.
theorem toHeap_of_steps {c c₂ : Cmd} {s s₂ : State} {h : Heap}
(hsteps : Steps (c, s) (c₂, s₂)) :
HSteps (c.toHeap, s, h) (c₂.toHeap, s₂, h)
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
abbrev Steps : Config → Config → Prop := Relation.ReflTransGen Step
CSLibExt/Languages/IMP/SmallStep.lean:55
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
Uses 12 · Used by 1
TheoremEmbedded plain commands are safe#✓fully proved
For every plain IMP command \(c\) with embedding \(\overline{c}\) into the heap language, every store \(s\) and every heap \(h\), the heap configuration \((\overline{c}, s, h)\) is safe.
This holds because plain IMP never gets stuck except at \(\mathtt{skip}\).
theorem safe_toHeap (c : Cmd) (s : State) (h : Heap) : Safe (c.toHeap, s, h)
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Safe (cfg : HConfig) : Prop :=
∀ cfg', HSteps cfg cfg' → cfg'.1 = .skip ∨ ∃ cfg'', HStep cfg' cfg''
CSLibExt/Languages/IMP/HeapStep.lean:97
Uses 18 · Used by 1
TheoremEmbedding preserves termination#✓fully proved
Let \(c\) be a plain IMP command with embedding \(\overline{c}\) into the heap language, let \(s, s'\) be stores and let \(h\) be a heap. Then \(c\) terminates from \(s\) with final store \(s'\) if and only if \((\overline{c}, s, h)\) reaches \((\mathtt{skip}, s', h)\) in zero or more heap steps.
theorem terminates_toHeap {c : Cmd} {s s' : State} {h : Heap} :
Terminates c s s' ↔ HSteps (c.toHeap, s, h) (.skip, s', h)
inductive Cmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : Cmd)
| ite (guard : BExp) (thenBranch elseBranch : Cmd)
| while (guard : BExp) (body : Cmd)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/Syntax.lean:55
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
def Terminates (command : Cmd) (initial final : State) : Prop :=
Steps (command, initial) (.skip, final)
CSLibExt/Languages/IMP/SmallStep.lean:58
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
Uses 12
DefinitionModified variables of a heap command#✓fully proved
The set \(\mathrm{mod}(c)\) of variables a heap command \(c\) may assign to is defined by recursion on \(c\). It is empty for \(\mathbf{skip}\), a heap write \([a] := e\) and a deallocation \(\mathbf{free}(a)\); it is \(\{x\}\) for an assignment \(x := a\), a heap read \(x := [a]\) and an allocation \(x := \mathbf{alloc}(e)\); it is \(\mathrm{mod}(c_1) \cup \mathrm{mod}(c_2)\) for a sequence \(c_1; c_2\) and for a conditional \(\mathbf{if}\ b\ \mathbf{then}\ c_1\ \mathbf{else}\ c_2\); and it is \(\mathrm{mod}(c_0)\) for a loop \(\mathbf{while}\ b\ \mathbf{do}\ c_0\).
def modVars : HeapCmd → Finset Nat
| .skip => ∅
| .assign name _ => {name}
| .seq first second => first.modVars ∪ second.modVars
| .ite _ thenBranch elseBranch => thenBranch.modVars ∪ elseBranch.modVars
| .while _ body => body.modVars
| .read name _ => {name}
| .write _ _ => ∅
| .alloc name _ => {name}
| .free _ => ∅
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
Uses 3 · Used by 6
TheoremSteps do not enlarge the modified variables#✓fully proved
Write \(\mathrm{mod}(c)\) for the set of variables a heap command \(c\) may assign to. If the configuration \((c, s, h)\) takes a small step to \((c', s', h')\), then \(\mathrm{mod}(c') \subseteq \mathrm{mod}(c)\).
theorem modVars_subset {c c' : HeapCmd} {s s' : State} {h h' : Heap}
(hstep : HStep (c, s, h) (c', s', h')) : c'.modVars ⊆ c.modVars
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 10 · Used by 1
TheoremA heap step only changes assignable variables#✓fully proved
If a heap configuration \((c, s, h)\) takes one heap step to \((c', s', h')\), then \(s'(x) = s(x)\) for every variable \(x\) outside the set of variables that \(c\) may assign to.
theorem store_agree {c c' : HeapCmd} {s s' : State} {h h' : Heap}
(hstep : HStep (c, s, h) (c', s', h')) :
∀ x, x ∉ c.modVars → s' x = s x
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
inductive HStep : HConfig → HConfig → Prop
| assign (state) (name) (value) (heap) :
HStep (.assign name value, state, heap)
(.skip, Function.update state name (value.eval state), heap)
| seqSkip (second) (state) (heap) :
HStep (.seq .skip second, state, heap) (second, state, heap)
| seqStep {first first' second initial final heap heap'}
(step : HStep (first, initial, heap) (first', final, heap')) :
HStep (.seq first second, initial, heap) (.seq first' second, final, heap')
| iteTrue {guard thenBranch elseBranch state heap}
(guardTrue : guard.eval state = true) :
HStep (.ite guard thenBranch elseBranch, state, heap) (thenBranch, state, heap)
⋯
CSLibExt/Languages/IMP/HeapStep.lean:56
Uses 10 · Used by 1
TheoremHeap executions only change assignable variables#✓fully proved
If a heap configuration \((c, s, h)\) reaches a heap configuration \((c', s', h')\) in zero or more heap steps, then \(s'(x) = s(x)\) for every variable \(x\) outside the set of variables that \(c\) may assign to.
theorem store_agree {c c' : HeapCmd} {s s' : State} {h h' : Heap}
(hsteps : HSteps (c, s, h) (c', s', h')) :
∀ x, x ∉ c.modVars → s' x = s x
inductive HeapCmd where
| skip
| assign (name : Nat) (value : AExp)
| seq (first second : HeapCmd)
| ite (guard : BExp) (thenBranch elseBranch : HeapCmd)
| while (guard : BExp) (body : HeapCmd)
| read (name : Nat) (addr : AExp)
| write (addr value : AExp)
| alloc (name : Nat) (value : AExp)
| free (addr : AExp)
deriving DecidableEq, Repr
CSLibExt/Languages/IMP/HeapStep.lean:40
abbrev State := Nat → Nat
CSLibExt/Languages/IMP/Syntax.lean:34
abbrev Heap := Finmap (fun _ : Nat => Nat)
CSLibExt/Languages/IMP/Heap.lean:35
abbrev HSteps : HConfig → HConfig → Prop := Relation.ReflTransGen HStep
CSLibExt/Languages/IMP/HeapStep.lean:93
Uses 9 · Used by 1
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.