| author | paulson <lp15@cam.ac.uk> | 
| Thu, 19 Jan 2023 13:55:38 +0000 | |
| changeset 77003 | ab905b5bb206 | 
| parent 75653 | ea4f5b0ef497 | 
| child 77232 | 6cad6ed2700a | 
| permissions | -rw-r--r-- | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
1  | 
(* Title: HOL/Imperative_HOL/Heap_Monad.thy  | 
| 26170 | 2  | 
Author: John Matthews, Galois Connections; Alexander Krauss, Lukas Bulwahn & Florian Haftmann, TU Muenchen  | 
3  | 
*)  | 
|
4  | 
||
| 63167 | 5  | 
section \<open>A monad with a polymorphic heap and primitive reasoning infrastructure\<close>  | 
| 26170 | 6  | 
|
7  | 
theory Heap_Monad  | 
|
| 
41413
 
64cd30d6b0b8
explicit file specifications -- avoid secondary load path;
 
wenzelm 
parents: 
40671 
diff
changeset
 | 
8  | 
imports  | 
| 
 
64cd30d6b0b8
explicit file specifications -- avoid secondary load path;
 
wenzelm 
parents: 
40671 
diff
changeset
 | 
9  | 
Heap  | 
| 
66453
 
cc19f7ca2ed6
session-qualified theory imports: isabelle imports -U -i -d '~~/src/Benchmarks' -a;
 
wenzelm 
parents: 
66148 
diff
changeset
 | 
10  | 
"HOL-Library.Monad_Syntax"  | 
| 26170 | 11  | 
begin  | 
12  | 
||
| 63167 | 13  | 
subsection \<open>The monad\<close>  | 
| 26170 | 14  | 
|
| 63167 | 15  | 
subsubsection \<open>Monad construction\<close>  | 
| 26170 | 16  | 
|
| 63167 | 17  | 
text \<open>Monadic heap actions either produce values  | 
18  | 
and transform the heap, or fail\<close>  | 
|
| 58310 | 19  | 
datatype 'a Heap = Heap "heap \<Rightarrow> ('a \<times> heap) option"
 | 
| 26170 | 20  | 
|
| 66148 | 21  | 
declare [[code drop: "Code_Evaluation.term_of :: 'a::typerep Heap \<Rightarrow> Code_Evaluation.term"]]  | 
| 
40266
 
d72f1f734e5a
remove term_of equations for Heap type explicitly
 
haftmann 
parents: 
40173 
diff
changeset
 | 
22  | 
|
| 37709 | 23  | 
primrec execute :: "'a Heap \<Rightarrow> heap \<Rightarrow> ('a \<times> heap) option" where
 | 
24  | 
[code del]: "execute (Heap f) = f"  | 
|
| 26170 | 25  | 
|
| 37758 | 26  | 
lemma Heap_cases [case_names succeed fail]:  | 
27  | 
fixes f and h  | 
|
28  | 
assumes succeed: "\<And>x h'. execute f h = Some (x, h') \<Longrightarrow> P"  | 
|
29  | 
assumes fail: "execute f h = None \<Longrightarrow> P"  | 
|
30  | 
shows P  | 
|
31  | 
using assms by (cases "execute f h") auto  | 
|
32  | 
||
| 26170 | 33  | 
lemma Heap_execute [simp]:  | 
34  | 
"Heap (execute f) = f" by (cases f) simp_all  | 
|
35  | 
||
36  | 
lemma Heap_eqI:  | 
|
37  | 
"(\<And>h. execute f h = execute g h) \<Longrightarrow> f = g"  | 
|
| 
39302
 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 
nipkow 
parents: 
39250 
diff
changeset
 | 
38  | 
by (cases f, cases g) (auto simp: fun_eq_iff)  | 
| 26170 | 39  | 
|
| 57956 | 40  | 
named_theorems execute_simps "simplification rules for execute"  | 
| 37758 | 41  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
42  | 
lemma execute_Let [execute_simps]:  | 
| 37758 | 43  | 
"execute (let x = t in f x) = (let x = t in execute (f x))"  | 
44  | 
by (simp add: Let_def)  | 
|
45  | 
||
46  | 
||
| 63167 | 47  | 
subsubsection \<open>Specialised lifters\<close>  | 
| 37758 | 48  | 
|
49  | 
definition tap :: "(heap \<Rightarrow> 'a) \<Rightarrow> 'a Heap" where  | 
|
50  | 
[code del]: "tap f = Heap (\<lambda>h. Some (f h, h))"  | 
|
51  | 
||
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
52  | 
lemma execute_tap [execute_simps]:  | 
| 37758 | 53  | 
"execute (tap f) h = Some (f h, h)"  | 
54  | 
by (simp add: tap_def)  | 
|
| 26170 | 55  | 
|
| 37709 | 56  | 
definition heap :: "(heap \<Rightarrow> 'a \<times> heap) \<Rightarrow> 'a Heap" where  | 
57  | 
[code del]: "heap f = Heap (Some \<circ> f)"  | 
|
| 26170 | 58  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
59  | 
lemma execute_heap [execute_simps]:  | 
| 37709 | 60  | 
"execute (heap f) = Some \<circ> f"  | 
| 26170 | 61  | 
by (simp add: heap_def)  | 
62  | 
||
| 37754 | 63  | 
definition guard :: "(heap \<Rightarrow> bool) \<Rightarrow> (heap \<Rightarrow> 'a \<times> heap) \<Rightarrow> 'a Heap" where  | 
64  | 
[code del]: "guard P f = Heap (\<lambda>h. if P h then Some (f h) else None)"  | 
|
65  | 
||
| 37758 | 66  | 
lemma execute_guard [execute_simps]:  | 
| 37754 | 67  | 
"\<not> P h \<Longrightarrow> execute (guard P f) h = None"  | 
68  | 
"P h \<Longrightarrow> execute (guard P f) h = Some (f h)"  | 
|
69  | 
by (simp_all add: guard_def)  | 
|
70  | 
||
| 37758 | 71  | 
|
| 63167 | 72  | 
subsubsection \<open>Predicate classifying successful computations\<close>  | 
| 37758 | 73  | 
|
74  | 
definition success :: "'a Heap \<Rightarrow> heap \<Rightarrow> bool" where  | 
|
75  | 
"success f h \<longleftrightarrow> execute f h \<noteq> None"  | 
|
76  | 
||
77  | 
lemma successI:  | 
|
78  | 
"execute f h \<noteq> None \<Longrightarrow> success f h"  | 
|
79  | 
by (simp add: success_def)  | 
|
80  | 
||
81  | 
lemma successE:  | 
|
82  | 
assumes "success f h"  | 
|
| 58510 | 83  | 
obtains r h' where "execute f h = Some (r, h')"  | 
84  | 
using assms by (auto simp: success_def)  | 
|
| 37758 | 85  | 
|
| 57956 | 86  | 
named_theorems success_intros "introduction rules for success"  | 
| 37758 | 87  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
88  | 
lemma success_tapI [success_intros]:  | 
| 37758 | 89  | 
"success (tap f) h"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
90  | 
by (rule successI) (simp add: execute_simps)  | 
| 37758 | 91  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
92  | 
lemma success_heapI [success_intros]:  | 
| 37758 | 93  | 
"success (heap f) h"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
94  | 
by (rule successI) (simp add: execute_simps)  | 
| 37758 | 95  | 
|
96  | 
lemma success_guardI [success_intros]:  | 
|
97  | 
"P h \<Longrightarrow> success (guard P f) h"  | 
|
98  | 
by (rule successI) (simp add: execute_guard)  | 
|
99  | 
||
100  | 
lemma success_LetI [success_intros]:  | 
|
101  | 
"x = t \<Longrightarrow> success (f x) h \<Longrightarrow> success (let x = t in f x) h"  | 
|
102  | 
by (simp add: Let_def)  | 
|
103  | 
||
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
104  | 
lemma success_ifI:  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
105  | 
"(c \<Longrightarrow> success t h) \<Longrightarrow> (\<not> c \<Longrightarrow> success e h) \<Longrightarrow>  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
106  | 
success (if c then t else e) h"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
107  | 
by (simp add: success_def)  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
108  | 
|
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
109  | 
|
| 63167 | 110  | 
subsubsection \<open>Predicate for a simple relational calculus\<close>  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
111  | 
|
| 63167 | 112  | 
text \<open>  | 
113  | 
The \<open>effect\<close> predicate states that when a computation \<open>c\<close>  | 
|
114  | 
runs with the heap \<open>h\<close> will result in return value \<open>r\<close>  | 
|
115  | 
and a heap \<open>h'\<close>, i.e.~no exception occurs.  | 
|
116  | 
\<close>  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
117  | 
|
| 40671 | 118  | 
definition effect :: "'a Heap \<Rightarrow> heap \<Rightarrow> heap \<Rightarrow> 'a \<Rightarrow> bool" where  | 
119  | 
effect_def: "effect c h h' r \<longleftrightarrow> execute c h = Some (r, h')"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
120  | 
|
| 40671 | 121  | 
lemma effectI:  | 
122  | 
"execute c h = Some (r, h') \<Longrightarrow> effect c h h' r"  | 
|
123  | 
by (simp add: effect_def)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
124  | 
|
| 40671 | 125  | 
lemma effectE:  | 
126  | 
assumes "effect c h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
127  | 
obtains "r = fst (the (execute c h))"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
128  | 
and "h' = snd (the (execute c h))"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
129  | 
and "success c h"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
130  | 
proof (rule that)  | 
| 40671 | 131  | 
from assms have *: "execute c h = Some (r, h')" by (simp add: effect_def)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
132  | 
then show "success c h" by (simp add: success_def)  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
133  | 
from * have "fst (the (execute c h)) = r" and "snd (the (execute c h)) = h'"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
134  | 
by simp_all  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
135  | 
then show "r = fst (the (execute c h))"  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
136  | 
and "h' = snd (the (execute c h))" by simp_all  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
137  | 
qed  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
138  | 
|
| 40671 | 139  | 
lemma effect_success:  | 
140  | 
"effect c h h' r \<Longrightarrow> success c h"  | 
|
141  | 
by (simp add: effect_def success_def)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
142  | 
|
| 40671 | 143  | 
lemma success_effectE:  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
144  | 
assumes "success c h"  | 
| 40671 | 145  | 
obtains r h' where "effect c h h' r"  | 
146  | 
using assms by (auto simp add: effect_def success_def)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
147  | 
|
| 40671 | 148  | 
lemma effect_deterministic:  | 
149  | 
assumes "effect f h h' a"  | 
|
150  | 
and "effect f h h'' b"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
151  | 
shows "a = b" and "h' = h''"  | 
| 40671 | 152  | 
using assms unfolding effect_def by auto  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
153  | 
|
| 57956 | 154  | 
named_theorems effect_intros "introduction rules for effect"  | 
| 59028 | 155  | 
and effect_elims "elimination rules for effect"  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
156  | 
|
| 40671 | 157  | 
lemma effect_LetI [effect_intros]:  | 
158  | 
assumes "x = t" "effect (f x) h h' r"  | 
|
159  | 
shows "effect (let x = t in f x) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
160  | 
using assms by simp  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
161  | 
|
| 40671 | 162  | 
lemma effect_LetE [effect_elims]:  | 
163  | 
assumes "effect (let x = t in f x) h h' r"  | 
|
164  | 
obtains "effect (f t) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
165  | 
using assms by simp  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
166  | 
|
| 40671 | 167  | 
lemma effect_ifI:  | 
168  | 
assumes "c \<Longrightarrow> effect t h h' r"  | 
|
169  | 
and "\<not> c \<Longrightarrow> effect e h h' r"  | 
|
170  | 
shows "effect (if c then t else e) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
171  | 
by (cases c) (simp_all add: assms)  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
172  | 
|
| 40671 | 173  | 
lemma effect_ifE:  | 
174  | 
assumes "effect (if c then t else e) h h' r"  | 
|
175  | 
obtains "c" "effect t h h' r"  | 
|
176  | 
| "\<not> c" "effect e h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
177  | 
using assms by (cases c) simp_all  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
178  | 
|
| 40671 | 179  | 
lemma effect_tapI [effect_intros]:  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
180  | 
assumes "h' = h" "r = f h"  | 
| 40671 | 181  | 
shows "effect (tap f) h h' r"  | 
182  | 
by (rule effectI) (simp add: assms execute_simps)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
183  | 
|
| 40671 | 184  | 
lemma effect_tapE [effect_elims]:  | 
185  | 
assumes "effect (tap f) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
186  | 
obtains "h' = h" and "r = f h"  | 
| 40671 | 187  | 
using assms by (rule effectE) (auto simp add: execute_simps)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
188  | 
|
| 40671 | 189  | 
lemma effect_heapI [effect_intros]:  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
190  | 
assumes "h' = snd (f h)" "r = fst (f h)"  | 
| 40671 | 191  | 
shows "effect (heap f) h h' r"  | 
192  | 
by (rule effectI) (simp add: assms execute_simps)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
193  | 
|
| 40671 | 194  | 
lemma effect_heapE [effect_elims]:  | 
195  | 
assumes "effect (heap f) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
196  | 
obtains "h' = snd (f h)" and "r = fst (f h)"  | 
| 40671 | 197  | 
using assms by (rule effectE) (simp add: execute_simps)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
198  | 
|
| 40671 | 199  | 
lemma effect_guardI [effect_intros]:  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
200  | 
assumes "P h" "h' = snd (f h)" "r = fst (f h)"  | 
| 40671 | 201  | 
shows "effect (guard P f) h h' r"  | 
202  | 
by (rule effectI) (simp add: assms execute_simps)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
203  | 
|
| 40671 | 204  | 
lemma effect_guardE [effect_elims]:  | 
205  | 
assumes "effect (guard P f) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
206  | 
obtains "h' = snd (f h)" "r = fst (f h)" "P h"  | 
| 40671 | 207  | 
using assms by (rule effectE)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
208  | 
(auto simp add: execute_simps elim!: successE, cases "P h", auto simp add: execute_simps)  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
209  | 
|
| 37758 | 210  | 
|
| 63167 | 211  | 
subsubsection \<open>Monad combinators\<close>  | 
| 26170 | 212  | 
|
| 37709 | 213  | 
definition return :: "'a \<Rightarrow> 'a Heap" where  | 
| 26170 | 214  | 
[code del]: "return x = heap (Pair x)"  | 
215  | 
||
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
216  | 
lemma execute_return [execute_simps]:  | 
| 37709 | 217  | 
"execute (return x) = Some \<circ> Pair x"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
218  | 
by (simp add: return_def execute_simps)  | 
| 26170 | 219  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
220  | 
lemma success_returnI [success_intros]:  | 
| 37758 | 221  | 
"success (return x) h"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
222  | 
by (rule successI) (simp add: execute_simps)  | 
| 37758 | 223  | 
|
| 40671 | 224  | 
lemma effect_returnI [effect_intros]:  | 
225  | 
"h = h' \<Longrightarrow> effect (return x) h h' x"  | 
|
226  | 
by (rule effectI) (simp add: execute_simps)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
227  | 
|
| 40671 | 228  | 
lemma effect_returnE [effect_elims]:  | 
229  | 
assumes "effect (return x) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
230  | 
obtains "r = x" "h' = h"  | 
| 40671 | 231  | 
using assms by (rule effectE) (simp add: execute_simps)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
232  | 
|
| 68028 | 233  | 
definition raise :: "String.literal \<Rightarrow> 'a Heap" \<comment> \<open>the literal is just decoration\<close>  | 
234  | 
where "raise s = Heap (\<lambda>_. None)"  | 
|
235  | 
||
| 69597 | 236  | 
code_datatype raise \<comment> \<open>avoid \<^const>\<open>Heap\<close> formally\<close>  | 
| 26170 | 237  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
238  | 
lemma execute_raise [execute_simps]:  | 
| 37709 | 239  | 
"execute (raise s) = (\<lambda>_. None)"  | 
| 26170 | 240  | 
by (simp add: raise_def)  | 
241  | 
||
| 40671 | 242  | 
lemma effect_raiseE [effect_elims]:  | 
243  | 
assumes "effect (raise x) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
244  | 
obtains "False"  | 
| 40671 | 245  | 
using assms by (rule effectE) (simp add: success_def execute_simps)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
246  | 
|
| 37792 | 247  | 
definition bind :: "'a Heap \<Rightarrow> ('a \<Rightarrow> 'b Heap) \<Rightarrow> 'b Heap" where
 | 
248  | 
[code del]: "bind f g = Heap (\<lambda>h. case execute f h of  | 
|
| 37709 | 249  | 
Some (x, h') \<Rightarrow> execute (g x) h'  | 
250  | 
| None \<Rightarrow> None)"  | 
|
251  | 
||
| 
52622
 
e0ff1625e96d
localized and modernized adhoc-overloading (patch by Christian Sternagel);
 
wenzelm 
parents: 
52435 
diff
changeset
 | 
252  | 
adhoc_overloading  | 
| 
 
e0ff1625e96d
localized and modernized adhoc-overloading (patch by Christian Sternagel);
 
wenzelm 
parents: 
52435 
diff
changeset
 | 
253  | 
Monad_Syntax.bind Heap_Monad.bind  | 
| 37792 | 254  | 
|
| 37758 | 255  | 
lemma execute_bind [execute_simps]:  | 
| 62026 | 256  | 
"execute f h = Some (x, h') \<Longrightarrow> execute (f \<bind> g) h = execute (g x) h'"  | 
257  | 
"execute f h = None \<Longrightarrow> execute (f \<bind> g) h = None"  | 
|
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
258  | 
by (simp_all add: bind_def)  | 
| 37709 | 259  | 
|
| 38409 | 260  | 
lemma execute_bind_case:  | 
| 62026 | 261  | 
"execute (f \<bind> g) h = (case (execute f h) of  | 
| 38409 | 262  | 
Some (x, h') \<Rightarrow> execute (g x) h' | None \<Rightarrow> None)"  | 
263  | 
by (simp add: bind_def)  | 
|
264  | 
||
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
265  | 
lemma execute_bind_success:  | 
| 62026 | 266  | 
"success f h \<Longrightarrow> execute (f \<bind> g) h = execute (g (fst (the (execute f h)))) (snd (the (execute f h)))"  | 
| 58510 | 267  | 
by (cases f h rule: Heap_cases) (auto elim: successE simp add: bind_def)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
268  | 
|
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
269  | 
lemma success_bind_executeI:  | 
| 62026 | 270  | 
"execute f h = Some (x, h') \<Longrightarrow> success (g x) h' \<Longrightarrow> success (f \<bind> g) h"  | 
| 58510 | 271  | 
by (auto intro!: successI elim: successE simp add: bind_def)  | 
| 37758 | 272  | 
|
| 40671 | 273  | 
lemma success_bind_effectI [success_intros]:  | 
| 62026 | 274  | 
"effect f h h' x \<Longrightarrow> success (g x) h' \<Longrightarrow> success (f \<bind> g) h"  | 
| 40671 | 275  | 
by (auto simp add: effect_def success_def bind_def)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
276  | 
|
| 40671 | 277  | 
lemma effect_bindI [effect_intros]:  | 
278  | 
assumes "effect f h h' r" "effect (g r) h' h'' r'"  | 
|
| 62026 | 279  | 
shows "effect (f \<bind> g) h h'' r'"  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
280  | 
using assms  | 
| 40671 | 281  | 
apply (auto intro!: effectI elim!: effectE successE)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
282  | 
apply (subst execute_bind, simp_all)  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
283  | 
done  | 
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
284  | 
|
| 40671 | 285  | 
lemma effect_bindE [effect_elims]:  | 
| 62026 | 286  | 
assumes "effect (f \<bind> g) h h'' r'"  | 
| 40671 | 287  | 
obtains h' r where "effect f h h' r" "effect (g r) h' h'' r'"  | 
288  | 
using assms by (auto simp add: effect_def bind_def split: option.split_asm)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
289  | 
|
| 
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
290  | 
lemma execute_bind_eq_SomeI:  | 
| 37878 | 291  | 
assumes "execute f h = Some (x, h')"  | 
292  | 
and "execute (g x) h' = Some (y, h'')"  | 
|
| 62026 | 293  | 
shows "execute (f \<bind> g) h = Some (y, h'')"  | 
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
294  | 
using assms by (simp add: bind_def)  | 
| 37754 | 295  | 
|
| 62026 | 296  | 
lemma return_bind [simp]: "return x \<bind> f = f x"  | 
| 
51485
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
297  | 
by (rule Heap_eqI) (simp add: execute_simps)  | 
| 37709 | 298  | 
|
| 62026 | 299  | 
lemma bind_return [simp]: "f \<bind> return = f"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
300  | 
by (rule Heap_eqI) (simp add: bind_def execute_simps split: option.splits)  | 
| 37709 | 301  | 
|
| 62026 | 302  | 
lemma bind_bind [simp]: "(f \<bind> g) \<bind> k = (f :: 'a Heap) \<bind> (\<lambda>x. g x \<bind> k)"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
303  | 
by (rule Heap_eqI) (simp add: bind_def execute_simps split: option.splits)  | 
| 37709 | 304  | 
|
| 62026 | 305  | 
lemma raise_bind [simp]: "raise e \<bind> f = raise e"  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
306  | 
by (rule Heap_eqI) (simp add: execute_simps)  | 
| 37709 | 307  | 
|
| 26170 | 308  | 
|
| 63167 | 309  | 
subsection \<open>Generic combinators\<close>  | 
| 26170 | 310  | 
|
| 63167 | 311  | 
subsubsection \<open>Assertions\<close>  | 
| 26170 | 312  | 
|
| 37709 | 313  | 
definition assert :: "('a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a Heap" where
 | 
| 68028 | 314  | 
"assert P x = (if P x then return x else raise STR ''assert'')"  | 
| 28742 | 315  | 
|
| 37758 | 316  | 
lemma execute_assert [execute_simps]:  | 
| 37754 | 317  | 
"P x \<Longrightarrow> execute (assert P x) h = Some (x, h)"  | 
318  | 
"\<not> P x \<Longrightarrow> execute (assert P x) h = None"  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
319  | 
by (simp_all add: assert_def execute_simps)  | 
| 37754 | 320  | 
|
| 37758 | 321  | 
lemma success_assertI [success_intros]:  | 
322  | 
"P x \<Longrightarrow> success (assert P x) h"  | 
|
323  | 
by (rule successI) (simp add: execute_assert)  | 
|
324  | 
||
| 40671 | 325  | 
lemma effect_assertI [effect_intros]:  | 
326  | 
"P x \<Longrightarrow> h' = h \<Longrightarrow> r = x \<Longrightarrow> effect (assert P x) h h' r"  | 
|
327  | 
by (rule effectI) (simp add: execute_assert)  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
328  | 
|
| 40671 | 329  | 
lemma effect_assertE [effect_elims]:  | 
330  | 
assumes "effect (assert P x) h h' r"  | 
|
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
331  | 
obtains "P x" "r = x" "h' = h"  | 
| 40671 | 332  | 
using assms by (rule effectE) (cases "P x", simp_all add: execute_assert success_def)  | 
| 
37771
 
1bec64044b5e
spelt out relational framework in a consistent way
 
haftmann 
parents: 
37758 
diff
changeset
 | 
333  | 
|
| 28742 | 334  | 
lemma assert_cong [fundef_cong]:  | 
335  | 
assumes "P = P'"  | 
|
336  | 
assumes "\<And>x. P' x \<Longrightarrow> f x = f' x"  | 
|
| 62026 | 337  | 
shows "(assert P x \<bind> f) = (assert P' x \<bind> f')"  | 
| 37754 | 338  | 
by (rule Heap_eqI) (insert assms, simp add: assert_def)  | 
| 28742 | 339  | 
|
| 37758 | 340  | 
|
| 63167 | 341  | 
subsubsection \<open>Plain lifting\<close>  | 
| 37758 | 342  | 
|
| 37754 | 343  | 
definition lift :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a \<Rightarrow> 'b Heap" where
 | 
344  | 
"lift f = return o f"  | 
|
| 37709 | 345  | 
|
| 37754 | 346  | 
lemma lift_collapse [simp]:  | 
347  | 
"lift f x = return (f x)"  | 
|
348  | 
by (simp add: lift_def)  | 
|
| 37709 | 349  | 
|
| 37754 | 350  | 
lemma bind_lift:  | 
| 62026 | 351  | 
"(f \<bind> lift g) = (f \<bind> (\<lambda>x. return (g x)))"  | 
| 37754 | 352  | 
by (simp add: lift_def comp_def)  | 
| 37709 | 353  | 
|
| 37758 | 354  | 
|
| 63167 | 355  | 
subsubsection \<open>Iteration -- warning: this is rarely useful!\<close>  | 
| 37758 | 356  | 
|
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
357  | 
primrec fold_map :: "('a \<Rightarrow> 'b Heap) \<Rightarrow> 'a list \<Rightarrow> 'b list Heap" where
 | 
| 
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
358  | 
"fold_map f [] = return []"  | 
| 37792 | 359  | 
| "fold_map f (x # xs) = do {
 | 
| 37709 | 360  | 
y \<leftarrow> f x;  | 
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
361  | 
ys \<leftarrow> fold_map f xs;  | 
| 37709 | 362  | 
return (y # ys)  | 
| 37792 | 363  | 
}"  | 
| 37709 | 364  | 
|
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
365  | 
lemma fold_map_append:  | 
| 62026 | 366  | 
"fold_map f (xs @ ys) = fold_map f xs \<bind> (\<lambda>xs. fold_map f ys \<bind> (\<lambda>ys. return (xs @ ys)))"  | 
| 37754 | 367  | 
by (induct xs) simp_all  | 
368  | 
||
| 37758 | 369  | 
lemma execute_fold_map_unchanged_heap [execute_simps]:  | 
| 37754 | 370  | 
assumes "\<And>x. x \<in> set xs \<Longrightarrow> \<exists>y. execute (f x) h = Some (y, h)"  | 
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
371  | 
shows "execute (fold_map f xs) h =  | 
| 37754 | 372  | 
Some (List.map (\<lambda>x. fst (the (execute (f x) h))) xs, h)"  | 
373  | 
using assms proof (induct xs)  | 
|
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
374  | 
case Nil show ?case by (simp add: execute_simps)  | 
| 37754 | 375  | 
next  | 
376  | 
case (Cons x xs)  | 
|
377  | 
from Cons.prems obtain y  | 
|
378  | 
where y: "execute (f x) h = Some (y, h)" by auto  | 
|
| 
37756
 
59caa6180fff
avoid slightly odd "M" suffix; rename mapM to fold_map (fold_map_abort would be more correct, though)
 
haftmann 
parents: 
37754 
diff
changeset
 | 
379  | 
moreover from Cons.prems Cons.hyps have "execute (fold_map f xs) h =  | 
| 37754 | 380  | 
Some (map (\<lambda>x. fst (the (execute (f x) h))) xs, h)" by auto  | 
| 
37787
 
30dc3abf4a58
theorem collections do not contain default rules any longer
 
haftmann 
parents: 
37772 
diff
changeset
 | 
381  | 
ultimately show ?case by (simp, simp only: execute_bind(1), simp add: execute_simps)  | 
| 37754 | 382  | 
qed  | 
383  | 
||
| 40267 | 384  | 
|
| 63167 | 385  | 
subsection \<open>Partial function definition setup\<close>  | 
| 40267 | 386  | 
|
387  | 
definition Heap_ord :: "'a Heap \<Rightarrow> 'a Heap \<Rightarrow> bool" where  | 
|
388  | 
"Heap_ord = img_ord execute (fun_ord option_ord)"  | 
|
389  | 
||
| 
44174
 
d1d79f0e1ea6
make more HOL theories work with separate set type
 
huffman 
parents: 
43324 
diff
changeset
 | 
390  | 
definition Heap_lub :: "'a Heap set \<Rightarrow> 'a Heap" where  | 
| 40267 | 391  | 
"Heap_lub = img_lub execute Heap (fun_lub (flat_lub None))"  | 
392  | 
||
| 
54630
 
9061af4d5ebc
restrict admissibility to non-empty chains to allow more syntax-directed proof rules
 
Andreas Lochbihler 
parents: 
53361 
diff
changeset
 | 
393  | 
lemma Heap_lub_empty: "Heap_lub {} = Heap Map.empty"
 | 
| 
 
9061af4d5ebc
restrict admissibility to non-empty chains to allow more syntax-directed proof rules
 
Andreas Lochbihler 
parents: 
53361 
diff
changeset
 | 
394  | 
by(simp add: Heap_lub_def img_lub_def fun_lub_def flat_lub_def)  | 
| 
 
9061af4d5ebc
restrict admissibility to non-empty chains to allow more syntax-directed proof rules
 
Andreas Lochbihler 
parents: 
53361 
diff
changeset
 | 
395  | 
|
| 
51485
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
396  | 
lemma heap_interpretation: "partial_function_definitions Heap_ord Heap_lub"  | 
| 40267 | 397  | 
proof -  | 
398  | 
have "partial_function_definitions (fun_ord option_ord) (fun_lub (flat_lub None))"  | 
|
399  | 
by (rule partial_function_lift) (rule flat_interpretation)  | 
|
400  | 
then have "partial_function_definitions (img_ord execute (fun_ord option_ord))  | 
|
401  | 
(img_lub execute Heap (fun_lub (flat_lub None)))"  | 
|
402  | 
by (rule partial_function_image) (auto intro: Heap_eqI)  | 
|
403  | 
then show "partial_function_definitions Heap_ord Heap_lub"  | 
|
404  | 
by (simp only: Heap_ord_def Heap_lub_def)  | 
|
405  | 
qed  | 
|
406  | 
||
| 61605 | 407  | 
interpretation heap: partial_function_definitions Heap_ord Heap_lub  | 
| 
61566
 
c3d6e570ccef
Keyword 'rewrites' identifies rewrite morphisms.
 
ballarin 
parents: 
59104 
diff
changeset
 | 
408  | 
  rewrites "Heap_lub {} \<equiv> Heap Map.empty"
 | 
| 
54630
 
9061af4d5ebc
restrict admissibility to non-empty chains to allow more syntax-directed proof rules
 
Andreas Lochbihler 
parents: 
53361 
diff
changeset
 | 
409  | 
by (fact heap_interpretation)(simp add: Heap_lub_empty)  | 
| 
51485
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
410  | 
|
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
411  | 
lemma heap_step_admissible:  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
412  | 
"option.admissible  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
413  | 
      (\<lambda>f:: 'a => ('b * 'c) option. \<forall>h h' r. f h = Some (r, h') \<longrightarrow> P x h h' r)"
 | 
| 
53361
 
1cb7d3c0cf31
move admissible out of class ccpo to avoid unnecessary class predicate in foundational theorems
 
Andreas Lochbihler 
parents: 
52728 
diff
changeset
 | 
414  | 
proof (rule ccpo.admissibleI)  | 
| 
51485
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
415  | 
  fix A :: "('a \<Rightarrow> ('b * 'c) option) set"
 | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
416  | 
assume ch: "Complete_Partial_Order.chain option.le_fun A"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
417  | 
and IH: "\<forall>f\<in>A. \<forall>h h' r. f h = Some (r, h') \<longrightarrow> P x h h' r"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
418  | 
  from ch have ch': "\<And>x. Complete_Partial_Order.chain option_ord {y. \<exists>f\<in>A. y = f x}" by (rule chain_fun)
 | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
419  | 
show "\<forall>h h' r. option.lub_fun A h = Some (r, h') \<longrightarrow> P x h h' r"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
420  | 
proof (intro allI impI)  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
421  | 
fix h h' r assume "option.lub_fun A h = Some (r, h')"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
422  | 
from flat_lub_in_chain[OF ch' this[unfolded fun_lub_def]]  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
423  | 
    have "Some (r, h') \<in> {y. \<exists>f\<in>A. y = f h}" by simp
 | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
424  | 
then have "\<exists>f\<in>A. f h = Some (r, h')" by auto  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
425  | 
with IH show "P x h h' r" by auto  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
426  | 
qed  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
427  | 
qed  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
428  | 
|
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
429  | 
lemma admissible_heap:  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
430  | 
"heap.admissible (\<lambda>f. \<forall>x h h' r. effect (f x) h h' r \<longrightarrow> P x h h' r)"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
431  | 
proof (rule admissible_fun[OF heap_interpretation])  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
432  | 
fix x  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
433  | 
show "ccpo.admissible Heap_lub Heap_ord (\<lambda>a. \<forall>h h' r. effect a h h' r \<longrightarrow> P x h h' r)"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
434  | 
unfolding Heap_ord_def Heap_lub_def  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
435  | 
proof (intro admissible_image partial_function_lift flat_interpretation)  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
436  | 
show "option.admissible ((\<lambda>a. \<forall>h h' r. effect a h h' r \<longrightarrow> P x h h' r) \<circ> Heap)"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
437  | 
unfolding comp_def effect_def execute.simps  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
438  | 
by (rule heap_step_admissible)  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
439  | 
qed (auto simp add: Heap_eqI)  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
440  | 
qed  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
441  | 
|
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
442  | 
lemma fixp_induct_heap:  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
443  | 
fixes F :: "'c \<Rightarrow> 'c" and  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
444  | 
U :: "'c \<Rightarrow> 'b \<Rightarrow> 'a Heap" and  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
445  | 
    C :: "('b \<Rightarrow> 'a Heap) \<Rightarrow> 'c" and
 | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
446  | 
P :: "'b \<Rightarrow> heap \<Rightarrow> heap \<Rightarrow> 'a \<Rightarrow> bool"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
447  | 
assumes mono: "\<And>x. monotone (fun_ord Heap_ord) Heap_ord (\<lambda>f. U (F (C f)) x)"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
448  | 
assumes eq: "f \<equiv> C (ccpo.fixp (fun_lub Heap_lub) (fun_ord Heap_ord) (\<lambda>f. U (F (C f))))"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
449  | 
assumes inverse2: "\<And>f. U (C f) = f"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
450  | 
assumes step: "\<And>f x h h' r. (\<And>x h h' r. effect (U f x) h h' r \<Longrightarrow> P x h h' r)  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
451  | 
\<Longrightarrow> effect (U (F f) x) h h' r \<Longrightarrow> P x h h' r"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
452  | 
assumes defined: "effect (U f x) h h' r"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
453  | 
shows "P x h h' r"  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
454  | 
using step defined heap.fixp_induct_uc[of U F C, OF mono eq inverse2 admissible_heap, of P]  | 
| 
54630
 
9061af4d5ebc
restrict admissibility to non-empty chains to allow more syntax-directed proof rules
 
Andreas Lochbihler 
parents: 
53361 
diff
changeset
 | 
455  | 
unfolding effect_def execute.simps  | 
| 
51485
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
456  | 
by blast  | 
| 
 
637aa1649ac7
added rudimentary induction rule for partial_function (heap)
 
krauss 
parents: 
51143 
diff
changeset
 | 
457  | 
|
| 69597 | 458  | 
declaration \<open>Partial_Function.init "heap" \<^term>\<open>heap.fixp_fun\<close>  | 
459  | 
  \<^term>\<open>heap.mono_body\<close> @{thm heap.fixp_rule_uc} @{thm heap.fixp_induct_uc}
 | 
|
| 63167 | 460  | 
  (SOME @{thm fixp_induct_heap})\<close>
 | 
| 
42949
 
618adb3584e5
separate initializations for different modes of partial_function -- generation of induction rules will be non-uniform
 
krauss 
parents: 
41413 
diff
changeset
 | 
461  | 
|
| 
 
618adb3584e5
separate initializations for different modes of partial_function -- generation of induction rules will be non-uniform
 
krauss 
parents: 
41413 
diff
changeset
 | 
462  | 
|
| 40267 | 463  | 
abbreviation "mono_Heap \<equiv> monotone (fun_ord Heap_ord) Heap_ord"  | 
464  | 
||
465  | 
lemma Heap_ordI:  | 
|
466  | 
assumes "\<And>h. execute x h = None \<or> execute x h = execute y h"  | 
|
467  | 
shows "Heap_ord x y"  | 
|
468  | 
using assms unfolding Heap_ord_def img_ord_def fun_ord_def flat_ord_def  | 
|
469  | 
by blast  | 
|
470  | 
||
471  | 
lemma Heap_ordE:  | 
|
472  | 
assumes "Heap_ord x y"  | 
|
473  | 
obtains "execute x h = None" | "execute x h = execute y h"  | 
|
474  | 
using assms unfolding Heap_ord_def img_ord_def fun_ord_def flat_ord_def  | 
|
475  | 
by atomize_elim blast  | 
|
476  | 
||
| 
46029
 
4a19e3d147c3
attribute code_abbrev superseedes code_unfold_post; tuned names and spacing
 
haftmann 
parents: 
45294 
diff
changeset
 | 
477  | 
lemma bind_mono [partial_function_mono]:  | 
| 40267 | 478  | 
assumes mf: "mono_Heap B" and mg: "\<And>y. mono_Heap (\<lambda>f. C y f)"  | 
| 62026 | 479  | 
shows "mono_Heap (\<lambda>f. B f \<bind> (\<lambda>y. C y f))"  | 
| 40267 | 480  | 
proof (rule monotoneI)  | 
481  | 
fix f g :: "'a \<Rightarrow> 'b Heap" assume fg: "fun_ord Heap_ord f g"  | 
|
482  | 
from mf  | 
|
483  | 
have 1: "Heap_ord (B f) (B g)" by (rule monotoneD) (rule fg)  | 
|
484  | 
from mg  | 
|
485  | 
have 2: "\<And>y'. Heap_ord (C y' f) (C y' g)" by (rule monotoneD) (rule fg)  | 
|
486  | 
||
| 62026 | 487  | 
have "Heap_ord (B f \<bind> (\<lambda>y. C y f)) (B g \<bind> (\<lambda>y. C y f))"  | 
| 40267 | 488  | 
(is "Heap_ord ?L ?R")  | 
489  | 
proof (rule Heap_ordI)  | 
|
490  | 
fix h  | 
|
491  | 
from 1 show "execute ?L h = None \<or> execute ?L h = execute ?R h"  | 
|
492  | 
by (rule Heap_ordE[where h = h]) (auto simp: execute_bind_case)  | 
|
493  | 
qed  | 
|
494  | 
also  | 
|
| 62026 | 495  | 
have "Heap_ord (B g \<bind> (\<lambda>y'. C y' f)) (B g \<bind> (\<lambda>y'. C y' g))"  | 
| 40267 | 496  | 
(is "Heap_ord ?L ?R")  | 
497  | 
proof (rule Heap_ordI)  | 
|
498  | 
fix h  | 
|
499  | 
show "execute ?L h = None \<or> execute ?L h = execute ?R h"  | 
|
500  | 
proof (cases "execute (B g) h")  | 
|
501  | 
case None  | 
|
502  | 
then have "execute ?L h = None" by (auto simp: execute_bind_case)  | 
|
503  | 
thus ?thesis ..  | 
|
504  | 
next  | 
|
505  | 
case Some  | 
|
506  | 
then obtain r h' where "execute (B g) h = Some (r, h')"  | 
|
507  | 
by (metis surjective_pairing)  | 
|
508  | 
then have "execute ?L h = execute (C r f) h'"  | 
|
509  | 
"execute ?R h = execute (C r g) h'"  | 
|
510  | 
by (auto simp: execute_bind_case)  | 
|
511  | 
with 2[of r] show ?thesis by (auto elim: Heap_ordE)  | 
|
512  | 
qed  | 
|
513  | 
qed  | 
|
514  | 
finally (heap.leq_trans)  | 
|
| 62026 | 515  | 
show "Heap_ord (B f \<bind> (\<lambda>y. C y f)) (B g \<bind> (\<lambda>y'. C y' g))" .  | 
| 40267 | 516  | 
qed  | 
517  | 
||
518  | 
||
| 63167 | 519  | 
subsection \<open>Code generator setup\<close>  | 
| 26182 | 520  | 
|
| 63167 | 521  | 
subsubsection \<open>SML and OCaml\<close>  | 
| 26182 | 522  | 
|
| 
52435
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
523  | 
code_printing type_constructor Heap \<rightharpoonup> (SML) "(unit/ ->/ _)"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
524  | 
code_printing constant bind \<rightharpoonup> (SML) "!(fn/ f'_/ =>/ fn/ ()/ =>/ f'_/ (_/ ())/ ())"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
525  | 
code_printing constant return \<rightharpoonup> (SML) "!(fn/ ()/ =>/ _)"  | 
| 68028 | 526  | 
code_printing constant Heap_Monad.raise \<rightharpoonup> (SML) "!(raise/ Fail/ _)"  | 
| 26182 | 527  | 
|
| 
52435
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
528  | 
code_printing type_constructor Heap \<rightharpoonup> (OCaml) "(unit/ ->/ _)"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
529  | 
code_printing constant bind \<rightharpoonup> (OCaml) "!(fun/ f'_/ ()/ ->/ f'_/ (_/ ())/ ())"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
530  | 
code_printing constant return \<rightharpoonup> (OCaml) "!(fun/ ()/ ->/ _)"  | 
| 68028 | 531  | 
code_printing constant Heap_Monad.raise \<rightharpoonup> (OCaml) "failwith"  | 
| 27707 | 532  | 
|
| 37838 | 533  | 
|
| 63167 | 534  | 
subsubsection \<open>Haskell\<close>  | 
| 37838 | 535  | 
|
| 63167 | 536  | 
text \<open>Adaption layer\<close>  | 
| 37838 | 537  | 
|
| 55372 | 538  | 
code_printing code_module "Heap" \<rightharpoonup> (Haskell)  | 
| 69690 | 539  | 
\<open>  | 
540  | 
module Heap(ST, RealWorld, STRef, newSTRef, readSTRef, writeSTRef,  | 
|
541  | 
STArray, newArray, newListArray, newFunArray, lengthArray, readArray, writeArray) where  | 
|
| 37838 | 542  | 
|
| 69690 | 543  | 
import Control.Monad(liftM)  | 
544  | 
import Control.Monad.ST(RealWorld, ST)  | 
|
545  | 
import Data.STRef(STRef, newSTRef, readSTRef, writeSTRef)  | 
|
546  | 
import qualified Data.Array.ST  | 
|
| 37838 | 547  | 
|
| 69690 | 548  | 
type STArray s a = Data.Array.ST.STArray s Integer a  | 
549  | 
||
550  | 
newArray :: Integer -> a -> ST s (STArray s a)  | 
|
551  | 
newArray k = Data.Array.ST.newArray (0, k - 1)  | 
|
| 37838 | 552  | 
|
| 69690 | 553  | 
newListArray :: [a] -> ST s (STArray s a)  | 
554  | 
newListArray xs = Data.Array.ST.newListArray (0, (fromInteger . toInteger . length) xs - 1) xs  | 
|
| 37838 | 555  | 
|
| 69690 | 556  | 
newFunArray :: Integer -> (Integer -> a) -> ST s (STArray s a)  | 
557  | 
newFunArray k f = Data.Array.ST.newListArray (0, k - 1) (map f [0..k-1])  | 
|
| 37838 | 558  | 
|
| 69690 | 559  | 
lengthArray :: STArray s a -> ST s Integer  | 
560  | 
lengthArray a = liftM (\(_, l) -> l + 1) (Data.Array.ST.getBounds a)  | 
|
| 37838 | 561  | 
|
| 69690 | 562  | 
readArray :: STArray s a -> Integer -> ST s a  | 
563  | 
readArray = Data.Array.ST.readArray  | 
|
| 37838 | 564  | 
|
| 69690 | 565  | 
writeArray :: STArray s a -> Integer -> a -> ST s ()  | 
566  | 
writeArray = Data.Array.ST.writeArray\<close>  | 
|
| 37838 | 567  | 
|
568  | 
code_reserved Haskell Heap  | 
|
569  | 
||
| 63167 | 570  | 
text \<open>Monad\<close>  | 
| 37838 | 571  | 
|
| 
52435
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
572  | 
code_printing type_constructor Heap \<rightharpoonup> (Haskell) "Heap.ST/ Heap.RealWorld/ _"  | 
| 37838 | 573  | 
code_monad bind Haskell  | 
| 
52435
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
574  | 
code_printing constant return \<rightharpoonup> (Haskell) "return"  | 
| 68028 | 575  | 
code_printing constant Heap_Monad.raise \<rightharpoonup> (Haskell) "error"  | 
| 37838 | 576  | 
|
577  | 
||
| 63167 | 578  | 
subsubsection \<open>Scala\<close>  | 
| 37838 | 579  | 
|
| 55372 | 580  | 
code_printing code_module "Heap" \<rightharpoonup> (Scala)  | 
| 63167 | 581  | 
\<open>object Heap {
 | 
| 
73137
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
582  | 
def bind[A, B](f: Unit => A, g: A => Unit => B): Unit => B = (_: Unit) => g(f(()))(())  | 
| 
38968
 
e55deaa22fff
do not print object frame around Scala includes -- this is in the responsibility of the user
 
haftmann 
parents: 
38773 
diff
changeset
 | 
583  | 
}  | 
| 37842 | 584  | 
|
585  | 
class Ref[A](x: A) {
 | 
|
586  | 
var value = x  | 
|
587  | 
}  | 
|
588  | 
||
589  | 
object Ref {
 | 
|
| 38771 | 590  | 
def apply[A](x: A): Ref[A] =  | 
591  | 
new Ref[A](x)  | 
|
592  | 
def lookup[A](r: Ref[A]): A =  | 
|
593  | 
r.value  | 
|
594  | 
def update[A](r: Ref[A], x: A): Unit =  | 
|
595  | 
    { r.value = x }
 | 
|
| 37842 | 596  | 
}  | 
597  | 
||
| 37964 | 598  | 
object Array {
 | 
| 
73137
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
599  | 
class T[A](n: Int)  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
600  | 
  {
 | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
601  | 
val array: Array[AnyRef] = new Array[AnyRef](n)  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
602  | 
def apply(i: Int): A = array(i).asInstanceOf[A]  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
603  | 
def update(i: Int, x: A): Unit = array(i) = x.asInstanceOf[AnyRef]  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
604  | 
def length: Int = array.length  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
605  | 
def toList: List[A] = array.toList.asInstanceOf[List[A]]  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
606  | 
    override def toString: String = array.mkString("Array.T(", ",", ")")
 | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
607  | 
}  | 
| 
75653
 
ea4f5b0ef497
minor performance tuning: avoid redundant BigInt construction;
 
wenzelm 
parents: 
73137 
diff
changeset
 | 
608  | 
  def init[A](n: Int)(f: Int => A): T[A] = {
 | 
| 
 
ea4f5b0ef497
minor performance tuning: avoid redundant BigInt construction;
 
wenzelm 
parents: 
73137 
diff
changeset
 | 
609  | 
val a = new T[A](n)  | 
| 
 
ea4f5b0ef497
minor performance tuning: avoid redundant BigInt construction;
 
wenzelm 
parents: 
73137 
diff
changeset
 | 
610  | 
for (i <- 0 until n) a(i) = f(i)  | 
| 
73137
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
611  | 
a  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
612  | 
}  | 
| 
75653
 
ea4f5b0ef497
minor performance tuning: avoid redundant BigInt construction;
 
wenzelm 
parents: 
73137 
diff
changeset
 | 
613  | 
def make[A](n: BigInt)(f: BigInt => A): T[A] = init(n.toInt)((i: Int) => f(BigInt(i)))  | 
| 
 
ea4f5b0ef497
minor performance tuning: avoid redundant BigInt construction;
 
wenzelm 
parents: 
73137 
diff
changeset
 | 
614  | 
def alloc[A](n: BigInt)(x: A): T[A] = init(n.toInt)(_ => x)  | 
| 
73137
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
615  | 
def len[A](a: T[A]): BigInt = BigInt(a.length)  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
616  | 
def nth[A](a: T[A], n: BigInt): A = a(n.toInt)  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
617  | 
def upd[A](a: T[A], n: BigInt, x: A): Unit = a.update(n.toInt, x)  | 
| 
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
618  | 
def freeze[A](a: T[A]): List[A] = a.toList  | 
| 
38968
 
e55deaa22fff
do not print object frame around Scala includes -- this is in the responsibility of the user
 
haftmann 
parents: 
38773 
diff
changeset
 | 
619  | 
}  | 
| 
73137
 
ca450d902198
updated to scala-2.13: its ArraySeq implementation is not usable here (requires scala.relection.ClassTag);
 
wenzelm 
parents: 
69690 
diff
changeset
 | 
620  | 
|
| 63167 | 621  | 
\<close>  | 
| 37842 | 622  | 
|
| 
38968
 
e55deaa22fff
do not print object frame around Scala includes -- this is in the responsibility of the user
 
haftmann 
parents: 
38773 
diff
changeset
 | 
623  | 
code_reserved Scala Heap Ref Array  | 
| 37838 | 624  | 
|
| 
52435
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
625  | 
code_printing type_constructor Heap \<rightharpoonup> (Scala) "(Unit/ =>/ _)"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
626  | 
code_printing constant bind \<rightharpoonup> (Scala) "Heap.bind"  | 
| 
 
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
 
haftmann 
parents: 
52388 
diff
changeset
 | 
627  | 
code_printing constant return \<rightharpoonup> (Scala) "('_: Unit)/ =>/ _"
 | 
| 68028 | 628  | 
code_printing constant Heap_Monad.raise \<rightharpoonup> (Scala) "!sys.error((_))"  | 
| 37838 | 629  | 
|
630  | 
||
| 63167 | 631  | 
subsubsection \<open>Target variants with less units\<close>  | 
| 37838 | 632  | 
|
| 63167 | 633  | 
setup \<open>  | 
| 31871 | 634  | 
|
635  | 
let  | 
|
| 27707 | 636  | 
|
| 31871 | 637  | 
open Code_Thingol;  | 
638  | 
||
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
639  | 
val imp_program =  | 
| 31871 | 640  | 
let  | 
| 69597 | 641  | 
val is_bind = curry (=) \<^const_name>\<open>bind\<close>;  | 
642  | 
val is_return = curry (=) \<^const_name>\<open>return\<close>;  | 
|
| 31893 | 643  | 
val dummy_name = "";  | 
644  | 
val dummy_case_term = IVar NONE;  | 
|
| 31871 | 645  | 
(*assumption: dummy values are not relevant for serialization*)  | 
| 69597 | 646  | 
val unitT = \<^type_name>\<open>unit\<close> `%% [];  | 
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
647  | 
val unitt =  | 
| 69597 | 648  | 
      IConst { sym = Code_Symbol.Constant \<^const_name>\<open>Unity\<close>, typargs = [], dicts = [], dom = [],
 | 
| 58397 | 649  | 
annotation = NONE };  | 
| 31871 | 650  | 
fun dest_abs ((v, ty) `|=> t, _) = ((v, ty), t)  | 
651  | 
| dest_abs (t, ty) =  | 
|
652  | 
let  | 
|
653  | 
val vs = fold_varnames cons t [];  | 
|
| 
43324
 
2b47822868e4
discontinued Name.variant to emphasize that this is old-style / indirect;
 
wenzelm 
parents: 
43080 
diff
changeset
 | 
654  | 
val v = singleton (Name.variant_list vs) "x";  | 
| 31871 | 655  | 
val ty' = (hd o fst o unfold_fun) ty;  | 
| 31893 | 656  | 
in ((SOME v, ty'), t `$ IVar (SOME v)) end;  | 
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
657  | 
    fun force (t as IConst { sym = Code_Symbol.Constant c, ... } `$ t') = if is_return c
 | 
| 31871 | 658  | 
then t' else t `$ unitt  | 
659  | 
| force t = t `$ unitt;  | 
|
| 38385 | 660  | 
fun tr_bind'' [(t1, _), (t2, ty2)] =  | 
| 31871 | 661  | 
let  | 
662  | 
val ((v, ty), t) = dest_abs (t2, ty2);  | 
|
| 
48072
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
663  | 
      in ICase { term = force t1, typ = ty, clauses = [(IVar v, tr_bind' t)], primitive = dummy_case_term } end
 | 
| 38385 | 664  | 
and tr_bind' t = case unfold_app t  | 
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
665  | 
     of (IConst { sym = Code_Symbol.Constant c, dom = ty1 :: ty2 :: _, ... }, [x1, x2]) => if is_bind c
 | 
| 38386 | 666  | 
then tr_bind'' [(x1, ty1), (x2, ty2)]  | 
667  | 
else force t  | 
|
668  | 
| _ => force t;  | 
|
| 
48072
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
669  | 
fun imp_monad_bind'' ts = (SOME dummy_name, unitT) `|=>  | 
| 
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
670  | 
      ICase { term = IVar (SOME dummy_name), typ = unitT, clauses = [(unitt, tr_bind'' ts)], primitive = dummy_case_term }
 | 
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
671  | 
    fun imp_monad_bind' (const as { sym = Code_Symbol.Constant c, dom = dom, ... }) ts = if is_bind c then case (ts, dom)
 | 
| 31871 | 672  | 
of ([t1, t2], ty1 :: ty2 :: _) => imp_monad_bind'' [(t1, ty1), (t2, ty2)]  | 
673  | 
| ([t1, t2, t3], ty1 :: ty2 :: _) => imp_monad_bind'' [(t1, ty1), (t2, ty2)] `$ t3  | 
|
674  | 
| (ts, _) => imp_monad_bind (eta_expand 2 (const, ts))  | 
|
675  | 
else IConst const `$$ map imp_monad_bind ts  | 
|
676  | 
and imp_monad_bind (IConst const) = imp_monad_bind' const []  | 
|
677  | 
| imp_monad_bind (t as IVar _) = t  | 
|
678  | 
| imp_monad_bind (t as _ `$ _) = (case unfold_app t  | 
|
679  | 
of (IConst const, ts) => imp_monad_bind' const ts  | 
|
680  | 
| (t, ts) => imp_monad_bind t `$$ map imp_monad_bind ts)  | 
|
681  | 
| imp_monad_bind (v_ty `|=> t) = v_ty `|=> imp_monad_bind t  | 
|
| 
48072
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
682  | 
      | imp_monad_bind (ICase { term = t, typ = ty, clauses = clauses, primitive = t0 }) =
 | 
| 
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
683  | 
          ICase { term = imp_monad_bind t, typ = ty,
 | 
| 
59058
 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 
wenzelm 
parents: 
59028 
diff
changeset
 | 
684  | 
clauses = (map o apply2) imp_monad_bind clauses, primitive = imp_monad_bind t0 };  | 
| 
28663
 
bd8438543bf2
code identifier namings are no longer imperative
 
haftmann 
parents: 
28562 
diff
changeset
 | 
685  | 
|
| 
55147
 
bce3dbc11f95
prefer explicit code symbol type over ad-hoc name mangling
 
haftmann 
parents: 
54630 
diff
changeset
 | 
686  | 
in (Code_Symbol.Graph.map o K o map_terms_stmt) imp_monad_bind end;  | 
| 27707 | 687  | 
|
688  | 
in  | 
|
689  | 
||
| 59104 | 690  | 
Code_Target.add_derived_target ("SML_imp", [("SML", imp_program)])
 | 
691  | 
#> Code_Target.add_derived_target ("OCaml_imp", [("OCaml", imp_program)])
 | 
|
692  | 
#> Code_Target.add_derived_target ("Scala_imp", [("Scala", imp_program)])
 | 
|
| 27707 | 693  | 
|
694  | 
end  | 
|
| 31871 | 695  | 
|
| 63167 | 696  | 
\<close>  | 
| 27707 | 697  | 
|
| 68028 | 698  | 
hide_const (open) Heap heap guard fold_map  | 
| 37724 | 699  | 
|
| 26170 | 700  | 
end  | 
| 
48072
 
ace701efe203
prefer records with speaking labels over deeply nested tuples
 
haftmann 
parents: 
46029 
diff
changeset
 | 
701  |