src/HOL/Library/Relational.thy
changeset 29399 ebcd69a00872
parent 29397 aab26a65e80f
child 29400 a462459fb5ce
equal deleted inserted replaced
29397:aab26a65e80f 29399:ebcd69a00872
     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