src/HOL/Imperative_HOL/Ref.thy
author haftmann
Mon Nov 22 09:37:39 2010 +0100 (2010-11-22)
changeset 40671 5e46057ba8e0
parent 39716 d1c12f4ee9ac
child 48073 1b609a7837ef
permissions -rw-r--r--
renamed slightly ambivalent crel to effect
     1 (*  Title:      HOL/Imperative_HOL/Ref.thy
     2     Author:     John Matthews, Galois Connections; Alexander Krauss, Lukas Bulwahn & Florian Haftmann, TU Muenchen
     3 *)
     4 
     5 header {* Monadic references *}
     6 
     7 theory Ref
     8 imports Array
     9 begin
    10 
    11 text {*
    12   Imperative reference operations; modeled after their ML counterparts.
    13   See http://caml.inria.fr/pub/docs/manual-caml-light/node14.15.html
    14   and http://www.smlnj.org/doc/Conversion/top-level-comparison.html
    15 *}
    16 
    17 subsection {* Primitives *}
    18 
    19 definition present :: "heap \<Rightarrow> 'a\<Colon>heap ref \<Rightarrow> bool" where
    20   "present h r \<longleftrightarrow> addr_of_ref r < lim h"
    21 
    22 definition get :: "heap \<Rightarrow> 'a\<Colon>heap ref \<Rightarrow> 'a" where
    23   "get h = from_nat \<circ> refs h TYPEREP('a) \<circ> addr_of_ref"
    24 
    25 definition set :: "'a\<Colon>heap ref \<Rightarrow> 'a \<Rightarrow> heap \<Rightarrow> heap" where
    26   "set r x = refs_update
    27     (\<lambda>h. h(TYPEREP('a) := ((h (TYPEREP('a))) (addr_of_ref r := to_nat x))))"
    28 
    29 definition alloc :: "'a \<Rightarrow> heap \<Rightarrow> 'a\<Colon>heap ref \<times> heap" where
    30   "alloc x h = (let
    31      l = lim h;
    32      r = Ref l
    33    in (r, set r x (h\<lparr>lim := l + 1\<rparr>)))"
    34 
    35 definition noteq :: "'a\<Colon>heap ref \<Rightarrow> 'b\<Colon>heap ref \<Rightarrow> bool" (infix "=!=" 70) where
    36   "r =!= s \<longleftrightarrow> TYPEREP('a) \<noteq> TYPEREP('b) \<or> addr_of_ref r \<noteq> addr_of_ref s"
    37 
    38 
    39 subsection {* Monad operations *}
    40 
    41 definition ref :: "'a\<Colon>heap \<Rightarrow> 'a ref Heap" where
    42   [code del]: "ref v = Heap_Monad.heap (alloc v)"
    43 
    44 definition lookup :: "'a\<Colon>heap ref \<Rightarrow> 'a Heap" ("!_" 61) where
    45   [code del]: "lookup r = Heap_Monad.tap (\<lambda>h. get h r)"
    46 
    47 definition update :: "'a ref \<Rightarrow> 'a\<Colon>heap \<Rightarrow> unit Heap" ("_ := _" 62) where
    48   [code del]: "update r v = Heap_Monad.heap (\<lambda>h. ((), set r v h))"
    49 
    50 definition change :: "('a\<Colon>heap \<Rightarrow> 'a) \<Rightarrow> 'a ref \<Rightarrow> 'a Heap" where
    51   "change f r = do {
    52      x \<leftarrow> ! r;
    53      let y = f x;
    54      r := y;
    55      return y
    56    }"
    57 
    58 
    59 subsection {* Properties *}
    60 
    61 text {* Primitives *}
    62 
    63 lemma noteq_sym: "r =!= s \<Longrightarrow> s =!= r"
    64   and unequal [simp]: "r \<noteq> r' \<longleftrightarrow> r =!= r'" -- "same types!"
    65   by (auto simp add: noteq_def)
    66 
    67 lemma noteq_irrefl: "r =!= r \<Longrightarrow> False"
    68   by (auto simp add: noteq_def)
    69 
    70 lemma present_alloc_neq: "present h r \<Longrightarrow> r =!= fst (alloc v h)"
    71   by (simp add: present_def alloc_def noteq_def Let_def)
    72 
    73 lemma next_fresh [simp]:
    74   assumes "(r, h') = alloc x h"
    75   shows "\<not> present h r"
    76   using assms by (cases h) (auto simp add: alloc_def present_def Let_def)
    77 
    78 lemma next_present [simp]:
    79   assumes "(r, h') = alloc x h"
    80   shows "present h' r"
    81   using assms by (cases h) (auto simp add: alloc_def set_def present_def Let_def)
    82 
    83 lemma get_set_eq [simp]:
    84   "get (set r x h) r = x"
    85   by (simp add: get_def set_def)
    86 
    87 lemma get_set_neq [simp]:
    88   "r =!= s \<Longrightarrow> get (set s x h) r = get h r"
    89   by (simp add: noteq_def get_def set_def)
    90 
    91 lemma set_same [simp]:
    92   "set r x (set r y h) = set r x h"
    93   by (simp add: set_def)
    94 
    95 lemma not_present_alloc [simp]:
    96   "\<not> present h (fst (alloc v h))"
    97   by (simp add: present_def alloc_def Let_def)
    98 
    99 lemma set_set_swap:
   100   "r =!= r' \<Longrightarrow> set r x (set r' x' h) = set r' x' (set r x h)"
   101   by (simp add: noteq_def set_def fun_eq_iff)
   102 
   103 lemma alloc_set:
   104   "fst (alloc x (set r x' h)) = fst (alloc x h)"
   105   by (simp add: alloc_def set_def Let_def)
   106 
   107 lemma get_alloc [simp]:
   108   "get (snd (alloc x h)) (fst (alloc x' h)) = x"
   109   by (simp add: alloc_def Let_def)
   110 
   111 lemma set_alloc [simp]:
   112   "set (fst (alloc v h)) v' (snd (alloc v h)) = snd (alloc v' h)"
   113   by (simp add: alloc_def Let_def)
   114 
   115 lemma get_alloc_neq: "r =!= fst (alloc v h) \<Longrightarrow> 
   116   get (snd (alloc v h)) r  = get h r"
   117   by (simp add: get_def set_def alloc_def Let_def noteq_def)
   118 
   119 lemma lim_set [simp]:
   120   "lim (set r v h) = lim h"
   121   by (simp add: set_def)
   122 
   123 lemma present_alloc [simp]: 
   124   "present h r \<Longrightarrow> present (snd (alloc v h)) r"
   125   by (simp add: present_def alloc_def Let_def)
   126 
   127 lemma present_set [simp]:
   128   "present (set r v h) = present h"
   129   by (simp add: present_def fun_eq_iff)
   130 
   131 lemma noteq_I:
   132   "present h r \<Longrightarrow> \<not> present h r' \<Longrightarrow> r =!= r'"
   133   by (auto simp add: noteq_def present_def)
   134 
   135 
   136 text {* Monad operations *}
   137 
   138 lemma execute_ref [execute_simps]:
   139   "execute (ref v) h = Some (alloc v h)"
   140   by (simp add: ref_def execute_simps)
   141 
   142 lemma success_refI [success_intros]:
   143   "success (ref v) h"
   144   by (auto intro: success_intros simp add: ref_def)
   145 
   146 lemma effect_refI [effect_intros]:
   147   assumes "(r, h') = alloc v h"
   148   shows "effect (ref v) h h' r"
   149   by (rule effectI) (insert assms, simp add: execute_simps)
   150 
   151 lemma effect_refE [effect_elims]:
   152   assumes "effect (ref v) h h' r"
   153   obtains "get h' r = v" and "present h' r" and "\<not> present h r"
   154   using assms by (rule effectE) (simp add: execute_simps)
   155 
   156 lemma execute_lookup [execute_simps]:
   157   "Heap_Monad.execute (lookup r) h = Some (get h r, h)"
   158   by (simp add: lookup_def execute_simps)
   159 
   160 lemma success_lookupI [success_intros]:
   161   "success (lookup r) h"
   162   by (auto intro: success_intros  simp add: lookup_def)
   163 
   164 lemma effect_lookupI [effect_intros]:
   165   assumes "h' = h" "x = get h r"
   166   shows "effect (!r) h h' x"
   167   by (rule effectI) (insert assms, simp add: execute_simps)
   168 
   169 lemma effect_lookupE [effect_elims]:
   170   assumes "effect (!r) h h' x"
   171   obtains "h' = h" "x = get h r"
   172   using assms by (rule effectE) (simp add: execute_simps)
   173 
   174 lemma execute_update [execute_simps]:
   175   "Heap_Monad.execute (update r v) h = Some ((), set r v h)"
   176   by (simp add: update_def execute_simps)
   177 
   178 lemma success_updateI [success_intros]:
   179   "success (update r v) h"
   180   by (auto intro: success_intros  simp add: update_def)
   181 
   182 lemma effect_updateI [effect_intros]:
   183   assumes "h' = set r v h"
   184   shows "effect (r := v) h h' x"
   185   by (rule effectI) (insert assms, simp add: execute_simps)
   186 
   187 lemma effect_updateE [effect_elims]:
   188   assumes "effect (r' := v) h h' r"
   189   obtains "h' = set r' v h"
   190   using assms by (rule effectE) (simp add: execute_simps)
   191 
   192 lemma execute_change [execute_simps]:
   193   "Heap_Monad.execute (change f r) h = Some (f (get h r), set r (f (get h r)) h)"
   194   by (simp add: change_def bind_def Let_def execute_simps)
   195 
   196 lemma success_changeI [success_intros]:
   197   "success (change f r) h"
   198   by (auto intro!: success_intros effect_intros simp add: change_def)
   199 
   200 lemma effect_changeI [effect_intros]: 
   201   assumes "h' = set r (f (get h r)) h" "x = f (get h r)"
   202   shows "effect (change f r) h h' x"
   203   by (rule effectI) (insert assms, simp add: execute_simps)  
   204 
   205 lemma effect_changeE [effect_elims]:
   206   assumes "effect (change f r') h h' r"
   207   obtains "h' = set r' (f (get h r')) h" "r = f (get h r')"
   208   using assms by (rule effectE) (simp add: execute_simps)
   209 
   210 lemma lookup_chain:
   211   "(!r \<guillemotright> f) = f"
   212   by (rule Heap_eqI) (auto simp add: lookup_def execute_simps intro: execute_bind)
   213 
   214 lemma update_change [code]:
   215   "r := e = change (\<lambda>_. e) r \<guillemotright> return ()"
   216   by (rule Heap_eqI) (simp add: change_def lookup_chain)
   217 
   218 
   219 text {* Non-interaction between imperative array and imperative references *}
   220 
   221 lemma array_get_set [simp]:
   222   "Array.get (set r v h) = Array.get h"
   223   by (simp add: Array.get_def set_def fun_eq_iff)
   224 
   225 lemma get_update [simp]:
   226   "get (Array.update a i v h) r = get h r"
   227   by (simp add: get_def Array.update_def Array.set_def)
   228 
   229 lemma alloc_update:
   230   "fst (alloc v (Array.update a i v' h)) = fst (alloc v h)"
   231   by (simp add: Array.update_def Array.get_def Array.set_def alloc_def Let_def)
   232 
   233 lemma update_set_swap:
   234   "Array.update a i v (set r v' h) = set r v' (Array.update a i v h)"
   235   by (simp add: Array.update_def Array.get_def Array.set_def set_def)
   236 
   237 lemma length_alloc [simp]: 
   238   "Array.length (snd (alloc v h)) a = Array.length h a"
   239   by (simp add: Array.length_def Array.get_def alloc_def set_def Let_def)
   240 
   241 lemma array_get_alloc [simp]: 
   242   "Array.get (snd (alloc v h)) = Array.get h"
   243   by (simp add: Array.get_def alloc_def set_def Let_def fun_eq_iff)
   244 
   245 lemma present_update [simp]: 
   246   "present (Array.update a i v h) = present h"
   247   by (simp add: Array.update_def Array.set_def fun_eq_iff present_def)
   248 
   249 lemma array_present_set [simp]:
   250   "Array.present (set r v h) = Array.present h"
   251   by (simp add: Array.present_def set_def fun_eq_iff)
   252 
   253 lemma array_present_alloc [simp]:
   254   "Array.present h a \<Longrightarrow> Array.present (snd (alloc v h)) a"
   255   by (simp add: Array.present_def alloc_def Let_def)
   256 
   257 lemma set_array_set_swap:
   258   "Array.set a xs (set r x' h) = set r x' (Array.set a xs h)"
   259   by (simp add: Array.set_def set_def)
   260 
   261 hide_const (open) present get set alloc noteq lookup update change
   262 
   263 
   264 subsection {* Code generator setup *}
   265 
   266 text {* Intermediate operation avoids invariance problem in @{text Scala} (similiar to value restriction) *}
   267 
   268 definition ref' where
   269   [code del]: "ref' = ref"
   270 
   271 lemma [code]:
   272   "ref x = ref' x"
   273   by (simp add: ref'_def)
   274 
   275 
   276 text {* SML / Eval *}
   277 
   278 code_type ref (SML "_/ ref")
   279 code_type ref (Eval "_/ Unsynchronized.ref")
   280 code_const Ref (SML "raise/ (Fail/ \"bare Ref\")")
   281 code_const ref' (SML "(fn/ ()/ =>/ ref/ _)")
   282 code_const ref' (Eval "(fn/ ()/ =>/ Unsynchronized.ref/ _)")
   283 code_const Ref.lookup (SML "(fn/ ()/ =>/ !/ _)")
   284 code_const Ref.update (SML "(fn/ ()/ =>/ _/ :=/ _)")
   285 code_const "HOL.equal :: 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" (SML infixl 6 "=")
   286 
   287 code_reserved Eval Unsynchronized
   288 
   289 
   290 text {* OCaml *}
   291 
   292 code_type ref (OCaml "_/ ref")
   293 code_const Ref (OCaml "failwith/ \"bare Ref\"")
   294 code_const ref' (OCaml "(fun/ ()/ ->/ ref/ _)")
   295 code_const Ref.lookup (OCaml "(fun/ ()/ ->/ !/ _)")
   296 code_const Ref.update (OCaml "(fun/ ()/ ->/ _/ :=/ _)")
   297 code_const "HOL.equal :: 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" (OCaml infixl 4 "=")
   298 
   299 code_reserved OCaml ref
   300 
   301 
   302 text {* Haskell *}
   303 
   304 code_type ref (Haskell "Heap.STRef/ Heap.RealWorld/ _")
   305 code_const Ref (Haskell "error/ \"bare Ref\"")
   306 code_const ref' (Haskell "Heap.newSTRef")
   307 code_const Ref.lookup (Haskell "Heap.readSTRef")
   308 code_const Ref.update (Haskell "Heap.writeSTRef")
   309 code_const "HOL.equal :: 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" (Haskell infix 4 "==")
   310 code_instance ref :: HOL.equal (Haskell -)
   311 
   312 
   313 text {* Scala *}
   314 
   315 code_type ref (Scala "!Ref[_]")
   316 code_const Ref (Scala "!error(\"bare Ref\")")
   317 code_const ref' (Scala "('_: Unit)/ =>/ Ref((_))")
   318 code_const Ref.lookup (Scala "('_: Unit)/ =>/ Ref.lookup((_))")
   319 code_const Ref.update (Scala "('_: Unit)/ =>/ Ref.update((_), (_))")
   320 code_const "HOL.equal :: 'a ref \<Rightarrow> 'a ref \<Rightarrow> bool" (Scala infixl 5 "==")
   321 
   322 end