1 theory Relational |
|
2 imports Array Ref |
|
3 begin |
|
4 |
|
5 section{* Definition of the Relational framework *} |
|
6 |
|
7 text {* The crel predicate states that when a computation c runs with the heap h |
|
8 will result in return value r and a heap h' (if no exception occurs). *} |
|
9 |
|
10 definition crel :: "'a Heap \<Rightarrow> heap \<Rightarrow> heap \<Rightarrow> 'a \<Rightarrow> bool" |
|
11 where |
|
12 crel_def': "crel c h h' r \<longleftrightarrow> Heap_Monad.execute c h = (Inl r, h')" |
|
13 |
|
14 lemma crel_def: -- FIXME |
|
15 "crel c h h' r \<longleftrightarrow> (Inl r, h') = Heap_Monad.execute c h" |
|
16 unfolding crel_def' by auto |
|
17 |
|
18 lemma crel_deterministic: "\<lbrakk> crel f h h' a; crel f h h'' b \<rbrakk> \<Longrightarrow> (a = b) \<and> (h' = h'')" |
|
19 unfolding crel_def' by auto |
|
20 |
|
21 section {* Elimination rules *} |
|
22 |
|
23 text {* For all commands, we define simple elimination rules. *} |
|
24 (* FIXME: consumes 1 necessary ?? *) |
|
25 |
|
26 subsection {* Elimination rules for basic monadic commands *} |
|
27 |
|
28 lemma crelE[consumes 1]: |
|
29 assumes "crel (f >>= g) h h'' r'" |
|
30 obtains h' r where "crel f h h' r" "crel (g r) h' h'' r'" |
|
31 using assms |
|
32 by (auto simp add: crel_def bindM_def Let_def prod_case_beta split_def Pair_fst_snd_eq split add: sum.split_asm) |
|
33 |
|
34 lemma crelE'[consumes 1]: |
|
35 assumes "crel (f >> g) h h'' r'" |
|
36 obtains h' r where "crel f h h' r" "crel g h' h'' r'" |
|
37 using assms |
|
38 by (elim crelE) auto |
|
39 |
|
40 lemma crel_return[consumes 1]: |
|
41 assumes "crel (return x) h h' r" |
|
42 obtains "r = x" "h = h'" |
|
43 using assms |
|
44 unfolding crel_def return_def by simp |
|
45 |
|
46 lemma crel_raise[consumes 1]: |
|
47 assumes "crel (raise x) h h' r" |
|
48 obtains "False" |
|
49 using assms |
|
50 unfolding crel_def raise_def by simp |
|
51 |
|
52 lemma crel_if: |
|
53 assumes "crel (if c then t else e) h h' r" |
|
54 obtains "c" "crel t h h' r" |
|
55 | "\<not>c" "crel e h h' r" |
|
56 using assms |
|
57 unfolding crel_def by auto |
|
58 |
|
59 lemma crel_option_case: |
|
60 assumes "crel (case x of None \<Rightarrow> n | Some y \<Rightarrow> s y) h h' r" |
|
61 obtains "x = None" "crel n h h' r" |
|
62 | y where "x = Some y" "crel (s y) h h' r" |
|
63 using assms |
|
64 unfolding crel_def by auto |
|
65 |
|
66 lemma crel_mapM: |
|
67 assumes "crel (mapM f xs) h h' r" |
|
68 assumes "\<And>h h'. P f [] h h' []" |
|
69 assumes "\<And>h h1 h' x xs y ys. \<lbrakk> crel (f x) h h1 y; crel (mapM f xs) h1 h' ys; P f xs h1 h' ys \<rbrakk> \<Longrightarrow> P f (x#xs) h h' (y#ys)" |
|
70 shows "P f xs h h' r" |
|
71 using assms(1) |
|
72 proof (induct xs arbitrary: h h' r) |
|
73 case Nil with assms(2) show ?case |
|
74 by (auto elim: crel_return) |
|
75 next |
|
76 case (Cons x xs) |
|
77 from Cons(2) obtain h1 y ys where crel_f: "crel (f x) h h1 y" |
|
78 and crel_mapM: "crel (mapM f xs) h1 h' ys" |
|
79 and r_def: "r = y#ys" |
|
80 unfolding mapM.simps |
|
81 by (auto elim!: crelE crel_return) |
|
82 from Cons(1)[OF crel_mapM] crel_mapM crel_f assms(3) r_def |
|
83 show ?case by auto |
|
84 qed |
|
85 |
|
86 lemma crel_heap: |
|
87 assumes "crel (Heap_Monad.heap f) h h' r" |
|
88 obtains "h' = snd (f h)" "r = fst (f h)" |
|
89 using assms |
|
90 unfolding heap_def crel_def apfst_def split_def prod_fun_def by simp_all |
|
91 |
|
92 subsection {* Elimination rules for array commands *} |
|
93 |
|
94 lemma crel_length: |
|
95 assumes "crel (length a) h h' r" |
|
96 obtains "h = h'" "r = Heap.length a h'" |
|
97 using assms |
|
98 unfolding length_def |
|
99 by (elim crel_heap) simp |
|
100 |
|
101 (* Strong version of the lemma for this operation is missing *) |
|
102 lemma crel_new_weak: |
|
103 assumes "crel (Array.new n v) h h' r" |
|
104 obtains "get_array r h' = List.replicate n v" |
|
105 using assms unfolding Array.new_def |
|
106 by (elim crel_heap) (auto simp:Heap.array_def Let_def split_def) |
|
107 |
|
108 lemma crel_nth[consumes 1]: |
|
109 assumes "crel (nth a i) h h' r" |
|
110 obtains "r = (get_array a h) ! i" "h = h'" "i < Heap.length a h" |
|
111 using assms |
|
112 unfolding nth_def |
|
113 by (auto elim!: crelE crel_if crel_raise crel_length crel_heap) |
|
114 |
|
115 lemma crel_upd[consumes 1]: |
|
116 assumes "crel (upd i v a) h h' r" |
|
117 obtains "r = a" "h' = Heap.upd a i v h" |
|
118 using assms |
|
119 unfolding upd_def |
|
120 by (elim crelE crel_if crel_return crel_raise |
|
121 crel_length crel_heap) auto |
|
122 |
|
123 (* Strong version of the lemma for this operation is missing *) |
|
124 lemma crel_of_list_weak: |
|
125 assumes "crel (Array.of_list xs) h h' r" |
|
126 obtains "get_array r h' = xs" |
|
127 using assms |
|
128 unfolding of_list_def |
|
129 by (elim crel_heap) (simp add:get_array_init_array_list) |
|
130 |
|
131 lemma crel_map_entry: |
|
132 assumes "crel (Array.map_entry i f a) h h' r" |
|
133 obtains "r = a" "h' = Heap.upd a i (f (get_array a h ! i)) h" |
|
134 using assms |
|
135 unfolding Array.map_entry_def |
|
136 by (elim crelE crel_upd crel_nth) auto |
|
137 |
|
138 lemma crel_swap: |
|
139 assumes "crel (Array.swap i x a) h h' r" |
|
140 obtains "r = get_array a h ! i" "h' = Heap.upd a i x h" |
|
141 using assms |
|
142 unfolding Array.swap_def |
|
143 by (elim crelE crel_upd crel_nth crel_return) auto |
|
144 |
|
145 (* Strong version of the lemma for this operation is missing *) |
|
146 lemma crel_make_weak: |
|
147 assumes "crel (Array.make n f) h h' r" |
|
148 obtains "i < n \<Longrightarrow> get_array r h' ! i = f i" |
|
149 using assms |
|
150 unfolding Array.make_def |
|
151 by (elim crel_of_list_weak) auto |
|
152 |
|
153 lemma upt_conv_Cons': |
|
154 assumes "Suc a \<le> b" |
|
155 shows "[b - Suc a..<b] = (b - Suc a)#[b - a..<b]" |
|
156 proof - |
|
157 from assms have l: "b - Suc a < b" by arith |
|
158 from assms have "Suc (b - Suc a) = b - a" by arith |
|
159 with l show ?thesis by (simp add: upt_conv_Cons) |
|
160 qed |
|
161 |
|
162 lemma crel_mapM_nth: |
|
163 assumes |
|
164 "crel (mapM (Array.nth a) [Heap.length a h - n..<Heap.length a h]) h h' xs" |
|
165 assumes "n \<le> Heap.length a h" |
|
166 shows "h = h' \<and> xs = drop (Heap.length a h - n) (get_array a h)" |
|
167 using assms |
|
168 proof (induct n arbitrary: xs h h') |
|
169 case 0 thus ?case |
|
170 by (auto elim!: crel_return simp add: Heap.length_def) |
|
171 next |
|
172 case (Suc n) |
|
173 from Suc(3) have "[Heap.length a h - Suc n..<Heap.length a h] = (Heap.length a h - Suc n)#[Heap.length a h - n..<Heap.length a h]" |
|
174 by (simp add: upt_conv_Cons') |
|
175 with Suc(2) obtain r where |
|
176 crel_mapM: "crel (mapM (Array.nth a) [Heap.length a h - n..<Heap.length a h]) h h' r" |
|
177 and xs_def: "xs = get_array a h ! (Heap.length a h - Suc n) # r" |
|
178 by (auto elim!: crelE crel_nth crel_return) |
|
179 from Suc(3) have "Heap.length a h - n = Suc (Heap.length a h - Suc n)" |
|
180 by arith |
|
181 with Suc.hyps[OF crel_mapM] xs_def show ?case |
|
182 unfolding Heap.length_def |
|
183 by (auto simp add: nth_drop') |
|
184 qed |
|
185 |
|
186 lemma crel_freeze: |
|
187 assumes "crel (Array.freeze a) h h' xs" |
|
188 obtains "h = h'" "xs = get_array a h" |
|
189 proof |
|
190 from assms have "crel (mapM (Array.nth a) [0..<Heap.length a h]) h h' xs" |
|
191 unfolding freeze_def |
|
192 by (auto elim: crelE crel_length) |
|
193 hence "crel (mapM (Array.nth a) [(Heap.length a h - Heap.length a h)..<Heap.length a h]) h h' xs" |
|
194 by simp |
|
195 from crel_mapM_nth[OF this] show "h = h'" and "xs = get_array a h" by auto |
|
196 qed |
|
197 |
|
198 lemma crel_mapM_map_entry_remains: |
|
199 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) h h' r" |
|
200 assumes "i < Heap.length a h - n" |
|
201 shows "get_array a h ! i = get_array a h' ! i" |
|
202 using assms |
|
203 proof (induct n arbitrary: h h' r) |
|
204 case 0 |
|
205 thus ?case |
|
206 by (auto elim: crel_return) |
|
207 next |
|
208 case (Suc n) |
|
209 let ?h1 = "Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h" |
|
210 from Suc(3) have "[Heap.length a h - Suc n..<Heap.length a h] = (Heap.length a h - Suc n)#[Heap.length a h - n..<Heap.length a h]" |
|
211 by (simp add: upt_conv_Cons') |
|
212 from Suc(2) this obtain r where |
|
213 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) ?h1 h' r" |
|
214 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
|
215 have length_remains: "Heap.length a ?h1 = Heap.length a h" by simp |
|
216 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a ?h1 - n..<Heap.length a ?h1]) ?h1 h' r" |
|
217 by simp |
|
218 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
|
219 qed |
|
220 |
|
221 lemma crel_mapM_map_entry_changes: |
|
222 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) h h' r" |
|
223 assumes "n \<le> Heap.length a h" |
|
224 assumes "i \<ge> Heap.length a h - n" |
|
225 assumes "i < Heap.length a h" |
|
226 shows "get_array a h' ! i = f (get_array a h ! i)" |
|
227 using assms |
|
228 proof (induct n arbitrary: h h' r) |
|
229 case 0 |
|
230 thus ?case |
|
231 by (auto elim!: crel_return) |
|
232 next |
|
233 case (Suc n) |
|
234 let ?h1 = "Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h" |
|
235 from Suc(3) have "[Heap.length a h - Suc n..<Heap.length a h] = (Heap.length a h - Suc n)#[Heap.length a h - n..<Heap.length a h]" |
|
236 by (simp add: upt_conv_Cons') |
|
237 from Suc(2) this obtain r where |
|
238 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) ?h1 h' r" |
|
239 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
|
240 have length_remains: "Heap.length a ?h1 = Heap.length a h" by simp |
|
241 from Suc(3) have less: "Heap.length a h - Suc n < Heap.length a h - n" by arith |
|
242 from Suc(3) have less2: "Heap.length a h - Suc n < Heap.length a h" by arith |
|
243 from Suc(4) length_remains have cases: "i = Heap.length a ?h1 - Suc n \<or> i \<ge> Heap.length a ?h1 - n" by arith |
|
244 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a ?h1 - n..<Heap.length a ?h1]) ?h1 h' r" |
|
245 by simp |
|
246 from Suc(1)[OF this] cases Suc(3) Suc(5) length_remains |
|
247 crel_mapM_map_entry_remains[OF this, of "Heap.length a h - Suc n", symmetric] less less2 |
|
248 show ?case |
|
249 by (auto simp add: nth_list_update_eq Heap.length_def) |
|
250 qed |
|
251 |
|
252 lemma crel_mapM_map_entry_length: |
|
253 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) h h' r" |
|
254 assumes "n \<le> Heap.length a h" |
|
255 shows "Heap.length a h' = Heap.length a h" |
|
256 using assms |
|
257 proof (induct n arbitrary: h h' r) |
|
258 case 0 |
|
259 thus ?case by (auto elim!: crel_return) |
|
260 next |
|
261 case (Suc n) |
|
262 let ?h1 = "Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h" |
|
263 from Suc(3) have "[Heap.length a h - Suc n..<Heap.length a h] = (Heap.length a h - Suc n)#[Heap.length a h - n..<Heap.length a h]" |
|
264 by (simp add: upt_conv_Cons') |
|
265 from Suc(2) this obtain r where |
|
266 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) ?h1 h' r" |
|
267 by (auto elim!: crelE crel_map_entry crel_return) |
|
268 have length_remains: "Heap.length a ?h1 = Heap.length a h" by simp |
|
269 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a ?h1 - n..<Heap.length a ?h1]) ?h1 h' r" |
|
270 by simp |
|
271 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
|
272 qed |
|
273 |
|
274 lemma crel_mapM_map_entry: |
|
275 assumes "crel (mapM (\<lambda>n. map_entry n f a) [0..<Heap.length a h]) h h' r" |
|
276 shows "get_array a h' = List.map f (get_array a h)" |
|
277 proof - |
|
278 from assms have "crel (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - Heap.length a h..<Heap.length a h]) h h' r" by simp |
|
279 from crel_mapM_map_entry_length[OF this] |
|
280 crel_mapM_map_entry_changes[OF this] show ?thesis |
|
281 unfolding Heap.length_def |
|
282 by (auto intro: nth_equalityI) |
|
283 qed |
|
284 |
|
285 lemma crel_map_weak: |
|
286 assumes crel_map: "crel (Array.map f a) h h' r" |
|
287 obtains "r = a" "get_array a h' = List.map f (get_array a h)" |
|
288 proof |
|
289 from assms crel_mapM_map_entry show "get_array a h' = List.map f (get_array a h)" |
|
290 unfolding Array.map_def |
|
291 by (fastsimp elim!: crelE crel_length crel_return) |
|
292 from assms show "r = a" |
|
293 unfolding Array.map_def |
|
294 by (elim crelE crel_return) |
|
295 qed |
|
296 |
|
297 subsection {* Elimination rules for reference commands *} |
|
298 |
|
299 (* TODO: |
|
300 maybe introduce a new predicate "extends h' h x" |
|
301 which means h' extends h with a new reference x. |
|
302 Then crel_new: would be |
|
303 assumes "crel (Ref.new v) h h' x" |
|
304 obtains "get_ref x h' = v" |
|
305 and "extends h' h x" |
|
306 |
|
307 and we would need further rules for extends: |
|
308 extends h' h x \<Longrightarrow> \<not> ref_present x h |
|
309 extends h' h x \<Longrightarrow> ref_present x h' |
|
310 extends h' h x \<Longrightarrow> ref_present y h \<Longrightarrow> ref_present y h' |
|
311 extends h' h x \<Longrightarrow> ref_present y h \<Longrightarrow> get_ref y h = get_ref y h' |
|
312 extends h' h x \<Longrightarrow> lim h' = Suc (lim h) |
|
313 *) |
|
314 |
|
315 lemma crel_Ref_new: |
|
316 assumes "crel (Ref.new v) h h' x" |
|
317 obtains "get_ref x h' = v" |
|
318 and "\<not> ref_present x h" |
|
319 and "ref_present x h'" |
|
320 and "\<forall>y. ref_present y h \<longrightarrow> get_ref y h = get_ref y h'" |
|
321 (* and "lim h' = Suc (lim h)" *) |
|
322 and "\<forall>y. ref_present y h \<longrightarrow> ref_present y h'" |
|
323 using assms |
|
324 unfolding Ref.new_def |
|
325 apply (elim crel_heap) |
|
326 unfolding Heap.ref_def |
|
327 apply (simp add: Let_def) |
|
328 unfolding Heap.new_ref_def |
|
329 apply (simp add: Let_def) |
|
330 unfolding ref_present_def |
|
331 apply auto |
|
332 unfolding get_ref_def set_ref_def |
|
333 apply auto |
|
334 done |
|
335 |
|
336 lemma crel_lookup: |
|
337 assumes "crel (!ref) h h' r" |
|
338 obtains "h = h'" "r = get_ref ref h" |
|
339 using assms |
|
340 unfolding Ref.lookup_def |
|
341 by (auto elim: crel_heap) |
|
342 |
|
343 lemma crel_update: |
|
344 assumes "crel (ref := v) h h' r" |
|
345 obtains "h' = set_ref ref v h" "r = ()" |
|
346 using assms |
|
347 unfolding Ref.update_def |
|
348 by (auto elim: crel_heap) |
|
349 |
|
350 lemma crel_change: |
|
351 assumes "crel (Ref.change f ref) h h' r" |
|
352 obtains "h' = set_ref ref (f (get_ref ref h)) h" "r = f (get_ref ref h)" |
|
353 using assms |
|
354 unfolding Ref.change_def Let_def |
|
355 by (auto elim!: crelE crel_lookup crel_update crel_return) |
|
356 |
|
357 subsection {* Elimination rules for the assert command *} |
|
358 |
|
359 lemma crel_assert[consumes 1]: |
|
360 assumes "crel (assert P x) h h' r" |
|
361 obtains "P x" "r = x" "h = h'" |
|
362 using assms |
|
363 unfolding assert_def |
|
364 by (elim crel_if crel_return crel_raise) auto |
|
365 |
|
366 lemma crel_assert_eq: "(\<And>h h' r. crel f h h' r \<Longrightarrow> P r) \<Longrightarrow> f \<guillemotright>= assert P = f" |
|
367 unfolding crel_def bindM_def Let_def assert_def |
|
368 raise_def return_def prod_case_beta |
|
369 apply (cases f) |
|
370 apply simp |
|
371 apply (simp add: expand_fun_eq split_def) |
|
372 apply auto |
|
373 apply (case_tac "fst (fun x)") |
|
374 apply (simp_all add: Pair_fst_snd_eq) |
|
375 apply (erule_tac x="x" in meta_allE) |
|
376 apply fastsimp |
|
377 done |
|
378 |
|
379 section {* Introduction rules *} |
|
380 |
|
381 subsection {* Introduction rules for basic monadic commands *} |
|
382 |
|
383 lemma crelI: |
|
384 assumes "crel f h h' r" "crel (g r) h' h'' r'" |
|
385 shows "crel (f >>= g) h h'' r'" |
|
386 using assms by (simp add: crel_def' bindM_def) |
|
387 |
|
388 lemma crelI': |
|
389 assumes "crel f h h' r" "crel g h' h'' r'" |
|
390 shows "crel (f >> g) h h'' r'" |
|
391 using assms by (intro crelI) auto |
|
392 |
|
393 lemma crel_returnI: |
|
394 shows "crel (return x) h h x" |
|
395 unfolding crel_def return_def by simp |
|
396 |
|
397 lemma crel_raiseI: |
|
398 shows "\<not> (crel (raise x) h h' r)" |
|
399 unfolding crel_def raise_def by simp |
|
400 |
|
401 lemma crel_ifI: |
|
402 assumes "c \<longrightarrow> crel t h h' r" |
|
403 "\<not>c \<longrightarrow> crel e h h' r" |
|
404 shows "crel (if c then t else e) h h' r" |
|
405 using assms |
|
406 unfolding crel_def by auto |
|
407 |
|
408 lemma crel_option_caseI: |
|
409 assumes "\<And>y. x = Some y \<Longrightarrow> crel (s y) h h' r" |
|
410 assumes "x = None \<Longrightarrow> crel n h h' r" |
|
411 shows "crel (case x of None \<Rightarrow> n | Some y \<Rightarrow> s y) h h' r" |
|
412 using assms |
|
413 by (auto split: option.split) |
|
414 |
|
415 lemma crel_heapI: |
|
416 shows "crel (Heap_Monad.heap f) h (snd (f h)) (fst (f h))" |
|
417 by (simp add: crel_def apfst_def split_def prod_fun_def) |
|
418 |
|
419 lemma crel_heapI': |
|
420 assumes "h' = snd (f h)" "r = fst (f h)" |
|
421 shows "crel (Heap_Monad.heap f) h h' r" |
|
422 using assms |
|
423 by (simp add: crel_def split_def apfst_def prod_fun_def) |
|
424 |
|
425 lemma crelI2: |
|
426 assumes "\<exists>h' rs'. crel f h h' rs' \<and> (\<exists>h'' rs. crel (g rs') h' h'' rs)" |
|
427 shows "\<exists>h'' rs. crel (f\<guillemotright>= g) h h'' rs" |
|
428 oops |
|
429 |
|
430 lemma crel_ifI2: |
|
431 assumes "c \<Longrightarrow> \<exists>h' r. crel t h h' r" |
|
432 "\<not> c \<Longrightarrow> \<exists>h' r. crel e h h' r" |
|
433 shows "\<exists> h' r. crel (if c then t else e) h h' r" |
|
434 oops |
|
435 |
|
436 subsection {* Introduction rules for array commands *} |
|
437 |
|
438 lemma crel_lengthI: |
|
439 shows "crel (length a) h h (Heap.length a h)" |
|
440 unfolding length_def |
|
441 by (rule crel_heapI') auto |
|
442 |
|
443 (* thm crel_newI for Array.new is missing *) |
|
444 |
|
445 lemma crel_nthI: |
|
446 assumes "i < Heap.length a h" |
|
447 shows "crel (nth a i) h h ((get_array a h) ! i)" |
|
448 using assms |
|
449 unfolding nth_def |
|
450 by (auto intro!: crelI crel_ifI crel_raiseI crel_lengthI crel_heapI') |
|
451 |
|
452 lemma crel_updI: |
|
453 assumes "i < Heap.length a h" |
|
454 shows "crel (upd i v a) h (Heap.upd a i v h) a" |
|
455 using assms |
|
456 unfolding upd_def |
|
457 by (auto intro!: crelI crel_ifI crel_returnI crel_raiseI |
|
458 crel_lengthI crel_heapI') |
|
459 |
|
460 (* thm crel_of_listI is missing *) |
|
461 |
|
462 (* thm crel_map_entryI is missing *) |
|
463 |
|
464 (* thm crel_swapI is missing *) |
|
465 |
|
466 (* thm crel_makeI is missing *) |
|
467 |
|
468 (* thm crel_freezeI is missing *) |
|
469 |
|
470 (* thm crel_mapI is missing *) |
|
471 |
|
472 subsection {* Introduction rules for reference commands *} |
|
473 |
|
474 lemma crel_lookupI: |
|
475 shows "crel (!ref) h h (get_ref ref h)" |
|
476 unfolding lookup_def by (auto intro!: crel_heapI') |
|
477 |
|
478 lemma crel_updateI: |
|
479 shows "crel (ref := v) h (set_ref ref v h) ()" |
|
480 unfolding update_def by (auto intro!: crel_heapI') |
|
481 |
|
482 lemma crel_changeI: |
|
483 shows "crel (Ref.change f ref) h (set_ref ref (f (get_ref ref h)) h) (f (get_ref ref h))" |
|
484 unfolding change_def Let_def by (auto intro!: crelI crel_returnI crel_lookupI crel_updateI) |
|
485 |
|
486 subsection {* Introduction rules for the assert command *} |
|
487 |
|
488 lemma crel_assertI: |
|
489 assumes "P x" |
|
490 shows "crel (assert P x) h h x" |
|
491 using assms |
|
492 unfolding assert_def |
|
493 by (auto intro!: crel_ifI crel_returnI crel_raiseI) |
|
494 |
|
495 section {* Defintion of the noError predicate *} |
|
496 |
|
497 text {* We add a simple definitional setting for crel intro rules |
|
498 where we only would like to show that the computation does not result in a exception for heap h, |
|
499 but we do not care about statements about the resulting heap and return value.*} |
|
500 |
|
501 definition noError :: "'a Heap \<Rightarrow> heap \<Rightarrow> bool" |
|
502 where |
|
503 "noError c h \<longleftrightarrow> (\<exists>r h'. (Inl r, h') = Heap_Monad.execute c h)" |
|
504 |
|
505 lemma noError_def': -- FIXME |
|
506 "noError c h \<longleftrightarrow> (\<exists>r h'. Heap_Monad.execute c h = (Inl r, h'))" |
|
507 unfolding noError_def apply auto proof - |
|
508 fix r h' |
|
509 assume "(Inl r, h') = Heap_Monad.execute c h" |
|
510 then have "Heap_Monad.execute c h = (Inl r, h')" .. |
|
511 then show "\<exists>r h'. Heap_Monad.execute c h = (Inl r, h')" by blast |
|
512 qed |
|
513 |
|
514 subsection {* Introduction rules for basic monadic commands *} |
|
515 |
|
516 lemma noErrorI: |
|
517 assumes "noError f h" |
|
518 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError (g r) h'" |
|
519 shows "noError (f \<guillemotright>= g) h" |
|
520 using assms |
|
521 by (auto simp add: noError_def' crel_def' bindM_def) |
|
522 |
|
523 lemma noErrorI': |
|
524 assumes "noError f h" |
|
525 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError g h'" |
|
526 shows "noError (f \<guillemotright> g) h" |
|
527 using assms |
|
528 by (auto simp add: noError_def' crel_def' bindM_def) |
|
529 |
|
530 lemma noErrorI2: |
|
531 "\<lbrakk>crel f h h' r ; noError f h; noError (g r) h'\<rbrakk> |
|
532 \<Longrightarrow> noError (f \<guillemotright>= g) h" |
|
533 by (auto simp add: noError_def' crel_def' bindM_def) |
|
534 |
|
535 lemma noError_return: |
|
536 shows "noError (return x) h" |
|
537 unfolding noError_def return_def |
|
538 by auto |
|
539 |
|
540 lemma noError_if: |
|
541 assumes "c \<Longrightarrow> noError t h" "\<not> c \<Longrightarrow> noError e h" |
|
542 shows "noError (if c then t else e) h" |
|
543 using assms |
|
544 unfolding noError_def |
|
545 by auto |
|
546 |
|
547 lemma noError_option_case: |
|
548 assumes "\<And>y. x = Some y \<Longrightarrow> noError (s y) h" |
|
549 assumes "noError n h" |
|
550 shows "noError (case x of None \<Rightarrow> n | Some y \<Rightarrow> s y) h" |
|
551 using assms |
|
552 by (auto split: option.split) |
|
553 |
|
554 lemma noError_mapM: |
|
555 assumes "\<forall>x \<in> set xs. noError (f x) h \<and> crel (f x) h h (r x)" |
|
556 shows "noError (mapM f xs) h" |
|
557 using assms |
|
558 proof (induct xs) |
|
559 case Nil |
|
560 thus ?case |
|
561 unfolding mapM.simps by (intro noError_return) |
|
562 next |
|
563 case (Cons x xs) |
|
564 thus ?case |
|
565 unfolding mapM.simps |
|
566 by (auto intro: noErrorI2[of "f x"] noErrorI noError_return) |
|
567 qed |
|
568 |
|
569 lemma noError_heap: |
|
570 shows "noError (Heap_Monad.heap f) h" |
|
571 by (simp add: noError_def' apfst_def prod_fun_def split_def) |
|
572 |
|
573 subsection {* Introduction rules for array commands *} |
|
574 |
|
575 lemma noError_length: |
|
576 shows "noError (Array.length a) h" |
|
577 unfolding length_def |
|
578 by (intro noError_heap) |
|
579 |
|
580 lemma noError_new: |
|
581 shows "noError (Array.new n v) h" |
|
582 unfolding Array.new_def by (intro noError_heap) |
|
583 |
|
584 lemma noError_upd: |
|
585 assumes "i < Heap.length a h" |
|
586 shows "noError (Array.upd i v a) h" |
|
587 using assms |
|
588 unfolding upd_def |
|
589 by (auto intro!: noErrorI noError_if noError_return noError_length noError_heap) (auto elim: crel_length) |
|
590 |
|
591 lemma noError_nth: |
|
592 assumes "i < Heap.length a h" |
|
593 shows "noError (Array.nth a i) h" |
|
594 using assms |
|
595 unfolding nth_def |
|
596 by (auto intro!: noErrorI noError_if noError_return noError_length noError_heap) (auto elim: crel_length) |
|
597 |
|
598 lemma noError_of_list: |
|
599 shows "noError (of_list ls) h" |
|
600 unfolding of_list_def by (rule noError_heap) |
|
601 |
|
602 lemma noError_map_entry: |
|
603 assumes "i < Heap.length a h" |
|
604 shows "noError (map_entry i f a) h" |
|
605 using assms |
|
606 unfolding map_entry_def |
|
607 by (auto elim: crel_nth intro!: noErrorI noError_nth noError_upd) |
|
608 |
|
609 lemma noError_swap: |
|
610 assumes "i < Heap.length a h" |
|
611 shows "noError (swap i x a) h" |
|
612 using assms |
|
613 unfolding swap_def |
|
614 by (auto elim: crel_nth intro!: noErrorI noError_return noError_nth noError_upd) |
|
615 |
|
616 lemma noError_make: |
|
617 shows "noError (make n f) h" |
|
618 unfolding make_def |
|
619 by (auto intro: noError_of_list) |
|
620 |
|
621 (*TODO: move to HeapMonad *) |
|
622 lemma mapM_append: |
|
623 "mapM f (xs @ ys) = mapM f xs \<guillemotright>= (\<lambda>xs. mapM f ys \<guillemotright>= (\<lambda>ys. return (xs @ ys)))" |
|
624 by (induct xs) (simp_all add: monad_simp) |
|
625 |
|
626 lemma noError_freeze: |
|
627 shows "noError (freeze a) h" |
|
628 unfolding freeze_def |
|
629 by (auto intro!: noErrorI noError_length noError_mapM[of _ _ _ "\<lambda>x. get_array a h ! x"] |
|
630 noError_nth crel_nthI elim: crel_length) |
|
631 |
|
632 lemma noError_mapM_map_entry: |
|
633 assumes "n \<le> Heap.length a h" |
|
634 shows "noError (mapM (\<lambda>n. map_entry n f a) [Heap.length a h - n..<Heap.length a h]) h" |
|
635 using assms |
|
636 proof (induct n arbitrary: h) |
|
637 case 0 |
|
638 thus ?case by (auto intro: noError_return) |
|
639 next |
|
640 case (Suc n) |
|
641 from Suc.prems have "[Heap.length a h - Suc n..<Heap.length a h] = (Heap.length a h - Suc n)#[Heap.length a h - n..<Heap.length a h]" |
|
642 by (simp add: upt_conv_Cons') |
|
643 with Suc.hyps[of "(Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h)"] Suc.prems show ?case |
|
644 by (auto simp add: intro!: noErrorI noError_return noError_map_entry elim: crel_map_entry) |
|
645 qed |
|
646 |
|
647 lemma noError_map: |
|
648 shows "noError (Array.map f a) h" |
|
649 using noError_mapM_map_entry[of "Heap.length a h" a h] |
|
650 unfolding Array.map_def |
|
651 by (auto intro: noErrorI noError_length noError_return elim!: crel_length) |
|
652 |
|
653 subsection {* Introduction rules for the reference commands *} |
|
654 |
|
655 lemma noError_Ref_new: |
|
656 shows "noError (Ref.new v) h" |
|
657 unfolding Ref.new_def by (intro noError_heap) |
|
658 |
|
659 lemma noError_lookup: |
|
660 shows "noError (!ref) h" |
|
661 unfolding lookup_def by (intro noError_heap) |
|
662 |
|
663 lemma noError_update: |
|
664 shows "noError (ref := v) h" |
|
665 unfolding update_def by (intro noError_heap) |
|
666 |
|
667 lemma noError_change: |
|
668 shows "noError (Ref.change f ref) h" |
|
669 unfolding Ref.change_def Let_def by (intro noErrorI noError_lookup noError_update noError_return) |
|
670 |
|
671 subsection {* Introduction rules for the assert command *} |
|
672 |
|
673 lemma noError_assert: |
|
674 assumes "P x" |
|
675 shows "noError (assert P x) h" |
|
676 using assms |
|
677 unfolding assert_def |
|
678 by (auto intro: noError_if noError_return) |
|
679 |
|
680 section {* Cumulative lemmas *} |
|
681 |
|
682 lemmas crel_elim_all = |
|
683 crelE crelE' crel_return crel_raise crel_if crel_option_case |
|
684 crel_length crel_new_weak crel_nth crel_upd crel_of_list_weak crel_map_entry crel_swap crel_make_weak crel_freeze crel_map_weak |
|
685 crel_Ref_new crel_lookup crel_update crel_change |
|
686 crel_assert |
|
687 |
|
688 lemmas crel_intro_all = |
|
689 crelI crelI' crel_returnI crel_raiseI crel_ifI crel_option_caseI |
|
690 crel_lengthI (* crel_newI *) crel_nthI crel_updI (* crel_of_listI crel_map_entryI crel_swapI crel_makeI crel_freezeI crel_mapI *) |
|
691 (* crel_Ref_newI *) crel_lookupI crel_updateI crel_changeI |
|
692 crel_assert |
|
693 |
|
694 lemmas noError_intro_all = |
|
695 noErrorI noErrorI' noError_return noError_if noError_option_case |
|
696 noError_length noError_new noError_nth noError_upd noError_of_list noError_map_entry noError_swap noError_make noError_freeze noError_map |
|
697 noError_Ref_new noError_lookup noError_update noError_change |
|
698 noError_assert |
|
699 |
|
700 end |
|