参考文档 / ZLIB × LEAN
Space.lean
此页源文件快照 ·
e22ebecf3a4f2f74 · 对应提交的原文 ↗本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。
1/-!
2# Runtime: the parts that do not mention the heap
3
4Trusted base of every translation; see `docs/trusted-base.md`. The heap itself is generated
5(`Schema.lean`, from the C headers). This file holds what the generated file builds on:
6
7* `upd`, the update of a table (a function from block numbers);
8* `Ptr R`, a pointer into an array: null, or the array (`R` says where it lives) and an index;
9* `Space`, which says how the heap stores the arrays of a reference type `R`;
10* `FnPtr`, a function pointer as a name;
11* `Junk`, the value of an uninitialised integer.
12-/
13
14namespace C
15
16/-- A table of the heap: the objects of one kind by block number, as an `Array`, so that code which uses the heap
17linearly updates it in place (`Tbl.modify`). Proofs see it as the function `Tbl.get t : Nat → α` (a coercion): entry
18`k` is `t.arr[k]` if that exists and `default` otherwise (`none` for a table of objects, `false` for the read-only
19flags). `upd` is the update; `upd_same`, `upd_ne`, `upd_upd`, `upd_self` are its rules. -/
20structure Tbl (α : Type) [Inhabited α] where
21 arr : Array α
22
23namespace Tbl
24variable {α : Type} [Inhabited α]
25
26/-- The entry `k`: `t.arr[k]`, or `default` beyond the end. -/
27def get (t : Tbl α) (k : Nat) : α := t.arr.getD k default
28instance : CoeFun (Tbl α) (fun _ => Nat → α) := ⟨Tbl.get⟩
29
30/-- The table with every entry `default`. -/
31def empty : Tbl α := ⟨#[]⟩
32
33instance : Inhabited (Tbl α) := ⟨empty⟩
34/-- `t` with the entry `k` replaced by `v` (the table grows when `k` is beyond its end). -/
35def set (t : Tbl α) (k : Nat) (v : α) : Tbl α :=
36 if k < t.arr.size then ⟨t.arr.set! k v⟩ else ⟨(t.arr ++ Array.replicate (k - t.arr.size) default).push v⟩
37/-- `t` with the entry `k` changed by `f`. The entry is taken out of the array, changed and put back, so it is
38updated in place when `t` and the entry are not shared. No change when `k` is beyond the end. -/
39def modify (t : Tbl α) (k : Nat) (f : α → α) : Tbl α := ⟨t.arr.modify k f⟩
40
41theorem get_eq (t : Tbl α) (k : Nat) : t.get k = (t.arr[k]?).getD default := by
42 simp [get, Array.getD_eq_getD_getElem?]
43
44theorem get_set (t : Tbl α) (k : Nat) (v : α) (x : Nat) :
45 (t.set k v).get x = if x = k then v else t.get x := by
46 unfold set
47 split
48 · rename_i h
49 simp [get_eq, Array.set!_eq_setIfInBounds, Array.getElem?_setIfInBounds]
50 split <;> simp_all [eq_comm]
51 · rename_i h
52 simp only [get_eq]
53 simp [Array.getElem?_push, Array.getElem?_append, Array.getElem?_replicate]
54 by_cases h1 : x < t.arr.size
55 · have : x ≠ k := by omega
56 simp [h1, this]
57 · by_cases h2 : x = k
58 · subst h2; simp [h1]
59 · simp [h1, h2]
60 have h3 : x - t.arr.size ≠ k - t.arr.size := by omega
61 simp [h3]
62 split <;> simp
63
64theorem get_empty (k : Nat) : (empty : Tbl α).get k = default := by
65 simp [get_eq, empty]
66
67@[simp] theorem get_empty_opt {β : Type} (k : Nat) : (empty : Tbl (Option β)).get k = none := by
68 simp [get_eq, empty]
69 rfl
70
71@[simp] theorem get_empty_bool (k : Nat) : (empty : Tbl Bool).get k = false := by
72 simp [get_eq, empty]
73
74theorem lt_size_of_get_ne (t : Tbl α) (k : Nat) (h : t.get k ≠ default) : k < t.arr.size := by
75 by_cases hc : k < t.arr.size
76 · exact hc
77 · exfalso
78 apply h
79 simp [get_eq, Array.getElem?_eq_none (by omega : t.arr.size ≤ k)]
80
81theorem modify_eq (t : Tbl α) (k : Nat) (f : α → α) (hk : k < t.arr.size) :
82 t.modify k f = t.set k (f (t.get k)) := by
83 unfold modify set
84 simp only [hk, ite_true]
85 congr 1
86 apply Array.ext_getElem?
87 intro i
88 simp [Array.getElem?_modify, Array.set!_eq_setIfInBounds, Array.getElem?_setIfInBounds, get_eq, hk]
89 split
90 · rename_i hki
91 subst hki
92 simp [Array.getElem?_eq_getElem hk]
93 · simp_all
94
95theorem set_self (t : Tbl α) (k : Nat) (hk : k < t.arr.size) : t.set k (t.get k) = t := by
96 obtain ⟨arr⟩ := t
97 have hk' : k < arr.size := hk
98 unfold set
99 simp only [hk', ite_true]
100 simp only [Tbl.mk.injEq]
101 apply Array.ext_getElem?
102 intro i
103 simp [Array.set!_eq_setIfInBounds, Array.getElem?_setIfInBounds, get_eq]
104 intro hki
105 subst hki
106 simp [hk', Array.getElem?_eq_getElem hk']
107
108theorem set_set (t : Tbl α) (k : Nat) (v v' : α) : (t.set k v).set k v' = t.set k v' := by
109 unfold set
110 split
111 · rename_i h
112 simp only [h, ite_true, Array.size_setIfInBounds, Array.set!_eq_setIfInBounds]
113 congr 1
114 apply Array.ext_getElem?
115 intro i
116 simp [Array.getElem?_setIfInBounds]
117 · rename_i h
118 have h2 : k < ((t.arr ++ Array.replicate (k - t.arr.size) default).push v).size := by simp; omega
119 simp only [h2, ite_true, Array.set!_eq_setIfInBounds]
120 congr 1
121 apply Array.ext_getElem?
122 intro i
123 simp [Array.getElem?_setIfInBounds, Array.getElem?_push, Array.getElem?_append]
124 by_cases hki : k = i
125 · subst hki
126 have h4 : k < t.arr.size + (k - t.arr.size + 1) := by omega
127 simp [h4, h]
128 · simp only [hki, ite_false]
129 by_cases h1 : i < t.arr.size
130 · simp [h1]
131 · have h3 : i - t.arr.size ≠ k - t.arr.size := by omega
132 simp [h1, h3]
133
134end Tbl
135/-- `t` with the entry `k` replaced by `v`: the update of a table of the heap. -/
136def upd {α : Type} [Inhabited α] (t : Tbl α) (k : Nat) (v : α) : Tbl α := t.set k v
137
138@[simp] theorem upd_same {α : Type} [Inhabited α] (t : Tbl α) (k : Nat) (v : α) : upd t k v k = v := by
139 have := Tbl.get_set t k v k
140 simpa [upd] using this
141@[simp] theorem upd_ne {α : Type} [Inhabited α] (t : Tbl α) (k : Nat) (v : α) (x : Nat) (h : x ≠ k) :
142 upd t k v x = t x := by
143 have := Tbl.get_set t k v x
144 simpa [upd, h] using this
145/-- The update as a function: the new value at `k`, the old table elsewhere. -/
146theorem upd_apply {α : Type} [Inhabited α] (t : Tbl α) (k : Nat) (v : α) (x : Nat) :
147 upd t k v x = if x = k then v else t x := by
148 have := Tbl.get_set t k v x
149 simpa [upd] using this
150
151theorem upd_upd {α : Type} [Inhabited α] (t : Tbl α) (k : Nat) (v v' : α) : upd (upd t k v) k v' = upd t k v' :=
152 Tbl.set_set t k v v'
153theorem upd_self {α : Type} (t : Tbl (Option α)) (k : Nat) (a : α) (hf : t k = some a) :
154 upd t k (some a) = t := by
155 have hk : k < t.arr.size := Tbl.lt_size_of_get_ne t k (by simp [Tbl.get] at hf ⊢; simp [hf])
156 have := Tbl.set_self t k hk
157 rw [show t.get k = some a from hf] at this
158 exact this
159
160/-- Changing an entry that holds `a` in place is the same as replacing it. -/
161theorem Tbl.modify_opt {β : Type} (t : Tbl (Option β)) (k : Nat) (g : β → β) (a : β) (hg : t k = some a) :
162 t.modify k (Option.map g) = upd t k (some (g a)) := by
163 have hk : k < t.arr.size := Tbl.lt_size_of_get_ne t k (by simp [Tbl.get] at hg ⊢; simp [hg])
164 rw [Tbl.modify_eq t k _ hk]
165 simp [upd, show t.get k = some a from hg]
166
167
168/-- A pointer into an array: null, or the array (`R` says where it lives: a heap block, an array inside a
169struct, a static table) and an index. There is no address. One past the end is a valid pointer. -/
170inductive Ptr (R : Type) where
171 | null
172 | ref (r : R) (off : Nat)
173 deriving DecidableEq
174
175instance {R : Type} : Inhabited (Ptr R) := ⟨.null⟩
176
177/-- How the heap stores the arrays that the reference type `R` denotes. `get h r` is the array (if it is live),
178`put h r a` the heap with that array replaced, `ro h r` says that the array is read-only. `modify h r f` is the heap
179with the array changed by `f`: the same as `put h r (f a)` (`modify_eq`) for a live array `a`, and it is what the
180primitives that write (`Ptr.store`, `Ptr.memcpy`, `Ptr.fill`) use, because it takes the array out of its table, so
181that `f` updates it in place when the heap is not shared. -/
182class Space (H : Type) (R : Type) (T : outParam Type) where
183 get : H → R → Option (Array T)
184 put : H → R → Array T → H
185 ro : H → R → Bool
186 modify : H → R → (Array T → Array T) → H
187 modify_eq : ∀ h r a f, get h r = some a → modify h r f = put h r (f a)
188
189/-- A function pointer: null, or the name of the function. -/
190inductive FnPtr where
191 | null
192 | fn (name : String)
193 deriving DecidableEq, Inhabited
194
195/-- The value of an uninitialised integer of type `T`, given an arbitrary 64-bit pattern. -/
196class Junk (T : Type) where
197 of : UInt64 → T
198
199instance : Junk UInt8 := ⟨UInt64.toUInt8⟩
200instance : Junk UInt16 := ⟨UInt64.toUInt16⟩
201instance : Junk UInt32 := ⟨UInt64.toUInt32⟩
202instance : Junk UInt64 := ⟨id⟩
203instance : Junk Int8 := ⟨fun x => x.toUInt8.toInt8⟩
204instance : Junk Int16 := ⟨fun x => x.toUInt16.toInt16⟩
205instance : Junk Int32 := ⟨fun x => x.toUInt32.toInt32⟩
206instance : Junk Int64 := ⟨UInt64.toInt64⟩
207
208end C