src/HOL/Imperative_HOL/ex/Linked_Lists.thy
author haftmann
Fri Jul 23 10:58:13 2010 +0200 (2010-07-23)
changeset 37947 844977c7abeb
parent 37879 443909380077
child 37959 6fe5fa827f18
permissions -rw-r--r--
avoid unreliable Haskell Int type
bulwahn@36098
     1
(*  Title:      HOL/Imperative_HOL/ex/Linked_Lists.thy
bulwahn@36098
     2
    Author:     Lukas Bulwahn, TU Muenchen
bulwahn@36098
     3
*)
bulwahn@36098
     4
bulwahn@36098
     5
header {* Linked Lists by ML references *}
bulwahn@36098
     6
bulwahn@34051
     7
theory Linked_Lists
haftmann@37771
     8
imports Imperative_HOL Code_Integer
bulwahn@34051
     9
begin
bulwahn@34051
    10
bulwahn@34051
    11
section {* Definition of Linked Lists *}
bulwahn@34051
    12
bulwahn@34051
    13
setup {* Sign.add_const_constraint (@{const_name Ref}, SOME @{typ "nat \<Rightarrow> 'a\<Colon>type ref"}) *}
bulwahn@34051
    14
datatype 'a node = Empty | Node 'a "('a node) ref"
bulwahn@34051
    15
haftmann@37725
    16
primrec
bulwahn@34051
    17
  node_encode :: "'a\<Colon>countable node \<Rightarrow> nat"
bulwahn@34051
    18
where
bulwahn@34051
    19
  "node_encode Empty = 0"
bulwahn@34051
    20
  | "node_encode (Node x r) = Suc (to_nat (x, r))"
bulwahn@34051
    21
bulwahn@34051
    22
instance node :: (countable) countable
bulwahn@34051
    23
proof (rule countable_classI [of "node_encode"])
bulwahn@34051
    24
  fix x y :: "'a\<Colon>countable node"
bulwahn@34051
    25
  show "node_encode x = node_encode y \<Longrightarrow> x = y"
bulwahn@34051
    26
  by (induct x, auto, induct y, auto, induct y, auto)
bulwahn@34051
    27
qed
bulwahn@34051
    28
bulwahn@34051
    29
instance node :: (heap) heap ..
bulwahn@34051
    30
haftmann@37725
    31
primrec make_llist :: "'a\<Colon>heap list \<Rightarrow> 'a node Heap"
bulwahn@34051
    32
where 
bulwahn@34051
    33
  [simp del]: "make_llist []     = return Empty"
krauss@37792
    34
            | "make_llist (x#xs) = do { tl \<leftarrow> make_llist xs;
krauss@37792
    35
                                        next \<leftarrow> ref tl;
krauss@37792
    36
                                        return (Node x next)
krauss@37792
    37
                                   }"
bulwahn@34051
    38
bulwahn@34051
    39
bulwahn@34051
    40
text {* define traverse using the MREC combinator *}
bulwahn@34051
    41
bulwahn@34051
    42
definition
bulwahn@34051
    43
  traverse :: "'a\<Colon>heap node \<Rightarrow> 'a list Heap"
bulwahn@34051
    44
where
haftmann@37771
    45
[code del]: "traverse = MREC (\<lambda>n. case n of Empty \<Rightarrow> return (Inl [])
krauss@37792
    46
                                | Node x r \<Rightarrow> do { tl \<leftarrow> Ref.lookup r;
krauss@37792
    47
                                                  return (Inr tl) })
bulwahn@34051
    48
                   (\<lambda>n tl xs. case n of Empty \<Rightarrow> undefined
bulwahn@34051
    49
                                      | Node x r \<Rightarrow> return (x # xs))"
bulwahn@34051
    50
bulwahn@34051
    51
bulwahn@34051
    52
lemma traverse_simps[code, simp]:
bulwahn@34051
    53
  "traverse Empty      = return []"
krauss@37792
    54
  "traverse (Node x r) = do { tl \<leftarrow> Ref.lookup r;
krauss@37792
    55
                              xs \<leftarrow> traverse tl;
krauss@37792
    56
                              return (x#xs)
krauss@37792
    57
                         }"
bulwahn@34051
    58
unfolding traverse_def
haftmann@37709
    59
by (auto simp: traverse_def MREC_rule)
bulwahn@34051
    60
bulwahn@34051
    61
bulwahn@34051
    62
section {* Proving correctness with relational abstraction *}
bulwahn@34051
    63
bulwahn@34051
    64
subsection {* Definition of list_of, list_of', refs_of and refs_of' *}
bulwahn@34051
    65
haftmann@37725
    66
primrec list_of :: "heap \<Rightarrow> ('a::heap) node \<Rightarrow> 'a list \<Rightarrow> bool"
bulwahn@34051
    67
where
bulwahn@34051
    68
  "list_of h r [] = (r = Empty)"
haftmann@37725
    69
| "list_of h r (a#as) = (case r of Empty \<Rightarrow> False | Node b bs \<Rightarrow> (a = b \<and> list_of h (Ref.get h bs) as))"
bulwahn@34051
    70
 
bulwahn@34051
    71
definition list_of' :: "heap \<Rightarrow> ('a::heap) node ref \<Rightarrow> 'a list \<Rightarrow> bool"
bulwahn@34051
    72
where
haftmann@37725
    73
  "list_of' h r xs = list_of h (Ref.get h r) xs"
bulwahn@34051
    74
haftmann@37725
    75
primrec refs_of :: "heap \<Rightarrow> ('a::heap) node \<Rightarrow> 'a node ref list \<Rightarrow> bool"
bulwahn@34051
    76
where
bulwahn@34051
    77
  "refs_of h r [] = (r = Empty)"
haftmann@37725
    78
| "refs_of h r (x#xs) = (case r of Empty \<Rightarrow> False | Node b bs \<Rightarrow> (x = bs) \<and> refs_of h (Ref.get h bs) xs)"
bulwahn@34051
    79
haftmann@37725
    80
primrec refs_of' :: "heap \<Rightarrow> ('a::heap) node ref \<Rightarrow> 'a node ref list \<Rightarrow> bool"
bulwahn@34051
    81
where
bulwahn@34051
    82
  "refs_of' h r [] = False"
haftmann@37725
    83
| "refs_of' h r (x#xs) = ((x = r) \<and> refs_of h (Ref.get h x) xs)"
bulwahn@34051
    84
bulwahn@34051
    85
bulwahn@34051
    86
subsection {* Properties of these definitions *}
bulwahn@34051
    87
bulwahn@34051
    88
lemma list_of_Empty[simp]: "list_of h Empty xs = (xs = [])"
bulwahn@34051
    89
by (cases xs, auto)
bulwahn@34051
    90
haftmann@37725
    91
lemma list_of_Node[simp]: "list_of h (Node x ps) xs = (\<exists>xs'. (xs = x # xs') \<and> list_of h (Ref.get h ps) xs')"
bulwahn@34051
    92
by (cases xs, auto)
bulwahn@34051
    93
haftmann@37725
    94
lemma list_of'_Empty[simp]: "Ref.get h q = Empty \<Longrightarrow> list_of' h q xs = (xs = [])"
bulwahn@34051
    95
unfolding list_of'_def by simp
bulwahn@34051
    96
haftmann@37725
    97
lemma list_of'_Node[simp]: "Ref.get h q = Node x ps \<Longrightarrow> list_of' h q xs = (\<exists>xs'. (xs = x # xs') \<and> list_of' h ps xs')"
bulwahn@34051
    98
unfolding list_of'_def by simp
bulwahn@34051
    99
haftmann@37725
   100
lemma list_of'_Nil: "list_of' h q [] \<Longrightarrow> Ref.get h q = Empty"
bulwahn@34051
   101
unfolding list_of'_def by simp
bulwahn@34051
   102
bulwahn@34051
   103
lemma list_of'_Cons: 
bulwahn@34051
   104
assumes "list_of' h q (x#xs)"
haftmann@37725
   105
obtains n where "Ref.get h q = Node x n" and "list_of' h n xs"
bulwahn@34051
   106
using assms unfolding list_of'_def by (auto split: node.split_asm)
bulwahn@34051
   107
bulwahn@34051
   108
lemma refs_of_Empty[simp] : "refs_of h Empty xs = (xs = [])"
bulwahn@34051
   109
  by (cases xs, auto)
bulwahn@34051
   110
haftmann@37725
   111
lemma refs_of_Node[simp]: "refs_of h (Node x ps) xs = (\<exists>prs. xs = ps # prs \<and> refs_of h (Ref.get h ps) prs)"
bulwahn@34051
   112
  by (cases xs, auto)
bulwahn@34051
   113
haftmann@37725
   114
lemma refs_of'_def': "refs_of' h p ps = (\<exists>prs. (ps = (p # prs)) \<and> refs_of h (Ref.get h p) prs)"
bulwahn@34051
   115
by (cases ps, auto)
bulwahn@34051
   116
bulwahn@34051
   117
lemma refs_of'_Node:
bulwahn@34051
   118
  assumes "refs_of' h p xs"
haftmann@37725
   119
  assumes "Ref.get h p = Node x pn"
bulwahn@34051
   120
  obtains pnrs
bulwahn@34051
   121
  where "xs = p # pnrs" and "refs_of' h pn pnrs"
bulwahn@34051
   122
using assms
bulwahn@34051
   123
unfolding refs_of'_def' by auto
bulwahn@34051
   124
bulwahn@34051
   125
lemma list_of_is_fun: "\<lbrakk> list_of h n xs; list_of h n ys\<rbrakk> \<Longrightarrow> xs = ys"
bulwahn@34051
   126
proof (induct xs arbitrary: ys n)
bulwahn@34051
   127
  case Nil thus ?case by auto
bulwahn@34051
   128
next
bulwahn@34051
   129
  case (Cons x xs')
bulwahn@34051
   130
  thus ?case
bulwahn@34051
   131
    by (cases ys,  auto split: node.split_asm)
bulwahn@34051
   132
qed
bulwahn@34051
   133
bulwahn@34051
   134
lemma refs_of_is_fun: "\<lbrakk> refs_of h n xs; refs_of h n ys\<rbrakk> \<Longrightarrow> xs = ys"
bulwahn@34051
   135
proof (induct xs arbitrary: ys n)
bulwahn@34051
   136
  case Nil thus ?case by auto
bulwahn@34051
   137
next
bulwahn@34051
   138
  case (Cons x xs')
bulwahn@34051
   139
  thus ?case
bulwahn@34051
   140
    by (cases ys,  auto split: node.split_asm)
bulwahn@34051
   141
qed
bulwahn@34051
   142
bulwahn@34051
   143
lemma refs_of'_is_fun: "\<lbrakk> refs_of' h p as; refs_of' h p bs \<rbrakk> \<Longrightarrow> as = bs"
bulwahn@34051
   144
unfolding refs_of'_def' by (auto dest: refs_of_is_fun)
bulwahn@34051
   145
bulwahn@34051
   146
bulwahn@34051
   147
lemma list_of_refs_of_HOL:
bulwahn@34051
   148
  assumes "list_of h r xs"
bulwahn@34051
   149
  shows "\<exists>rs. refs_of h r rs"
bulwahn@34051
   150
using assms
bulwahn@34051
   151
proof (induct xs arbitrary: r)
bulwahn@34051
   152
  case Nil thus ?case by auto
bulwahn@34051
   153
next
bulwahn@34051
   154
  case (Cons x xs')
bulwahn@34051
   155
  thus ?case
bulwahn@34051
   156
    by (cases r, auto)
bulwahn@34051
   157
qed
bulwahn@34051
   158
    
bulwahn@34051
   159
lemma list_of_refs_of:
bulwahn@34051
   160
  assumes "list_of h r xs"
bulwahn@34051
   161
  obtains rs where "refs_of h r rs"
bulwahn@34051
   162
using list_of_refs_of_HOL[OF assms]
bulwahn@34051
   163
by auto
bulwahn@34051
   164
bulwahn@34051
   165
lemma list_of'_refs_of'_HOL:
bulwahn@34051
   166
  assumes "list_of' h r xs"
bulwahn@34051
   167
  shows "\<exists>rs. refs_of' h r rs"
bulwahn@34051
   168
proof -
haftmann@37725
   169
  from assms obtain rs' where "refs_of h (Ref.get h r) rs'"
bulwahn@34051
   170
    unfolding list_of'_def by (rule list_of_refs_of)
bulwahn@34051
   171
  thus ?thesis unfolding refs_of'_def' by auto
bulwahn@34051
   172
qed
bulwahn@34051
   173
bulwahn@34051
   174
lemma list_of'_refs_of':
bulwahn@34051
   175
  assumes "list_of' h r xs"
bulwahn@34051
   176
  obtains rs where "refs_of' h r rs"
bulwahn@34051
   177
using list_of'_refs_of'_HOL[OF assms]
bulwahn@34051
   178
by auto
bulwahn@34051
   179
bulwahn@34051
   180
lemma refs_of_list_of_HOL:
bulwahn@34051
   181
  assumes "refs_of h r rs"
bulwahn@34051
   182
  shows "\<exists>xs. list_of h r xs"
bulwahn@34051
   183
using assms
bulwahn@34051
   184
proof (induct rs arbitrary: r)
bulwahn@34051
   185
  case Nil thus ?case by auto
bulwahn@34051
   186
next
bulwahn@34051
   187
  case (Cons r rs')
bulwahn@34051
   188
  thus ?case
bulwahn@34051
   189
    by (cases r, auto)
bulwahn@34051
   190
qed
bulwahn@34051
   191
bulwahn@34051
   192
lemma refs_of_list_of:
bulwahn@34051
   193
  assumes "refs_of h r rs"
bulwahn@34051
   194
  obtains xs where "list_of h r xs"
bulwahn@34051
   195
using refs_of_list_of_HOL[OF assms]
bulwahn@34051
   196
by auto
bulwahn@34051
   197
bulwahn@34051
   198
lemma refs_of'_list_of'_HOL:
bulwahn@34051
   199
  assumes "refs_of' h r rs"
bulwahn@34051
   200
  shows "\<exists>xs. list_of' h r xs"
bulwahn@34051
   201
using assms
bulwahn@34051
   202
unfolding list_of'_def refs_of'_def'
bulwahn@34051
   203
by (auto intro: refs_of_list_of)
bulwahn@34051
   204
bulwahn@34051
   205
bulwahn@34051
   206
lemma refs_of'_list_of':
bulwahn@34051
   207
  assumes "refs_of' h r rs"
bulwahn@34051
   208
  obtains xs where "list_of' h r xs"
bulwahn@34051
   209
using refs_of'_list_of'_HOL[OF assms]
bulwahn@34051
   210
by auto
bulwahn@34051
   211
bulwahn@34051
   212
lemma refs_of'E: "refs_of' h q rs \<Longrightarrow> q \<in> set rs"
bulwahn@34051
   213
unfolding refs_of'_def' by auto
bulwahn@34051
   214
bulwahn@34051
   215
lemma list_of'_refs_of'2:
bulwahn@34051
   216
  assumes "list_of' h r xs"
bulwahn@34051
   217
  shows "\<exists>rs'. refs_of' h r (r#rs')"
bulwahn@34051
   218
proof -
bulwahn@34051
   219
  from assms obtain rs where "refs_of' h r rs" by (rule list_of'_refs_of')
bulwahn@34051
   220
  thus ?thesis by (auto simp add: refs_of'_def')
bulwahn@34051
   221
qed
bulwahn@34051
   222
bulwahn@34051
   223
subsection {* More complicated properties of these predicates *}
bulwahn@34051
   224
bulwahn@34051
   225
lemma list_of_append:
bulwahn@34051
   226
  "list_of h n (as @ bs) \<Longrightarrow> \<exists>m. list_of h m bs"
bulwahn@34051
   227
apply (induct as arbitrary: n)
bulwahn@34051
   228
apply auto
bulwahn@34051
   229
apply (case_tac n)
bulwahn@34051
   230
apply auto
bulwahn@34051
   231
done
bulwahn@34051
   232
bulwahn@34051
   233
lemma refs_of_append: "refs_of h n (as @ bs) \<Longrightarrow> \<exists>m. refs_of h m bs"
bulwahn@34051
   234
apply (induct as arbitrary: n)
bulwahn@34051
   235
apply auto
bulwahn@34051
   236
apply (case_tac n)
bulwahn@34051
   237
apply auto
bulwahn@34051
   238
done
bulwahn@34051
   239
bulwahn@34051
   240
lemma refs_of_next:
haftmann@37725
   241
assumes "refs_of h (Ref.get h p) rs"
bulwahn@34051
   242
  shows "p \<notin> set rs"
bulwahn@34051
   243
proof (rule ccontr)
bulwahn@34051
   244
  assume a: "\<not> (p \<notin> set rs)"
bulwahn@34051
   245
  from this obtain as bs where split:"rs = as @ p # bs" by (fastsimp dest: split_list)
bulwahn@34051
   246
  with assms obtain q where "refs_of h q (p # bs)" by (fast dest: refs_of_append)
bulwahn@34051
   247
  with assms split show "False"
bulwahn@34051
   248
    by (cases q,auto dest: refs_of_is_fun)
bulwahn@34051
   249
qed
bulwahn@34051
   250
bulwahn@34051
   251
lemma refs_of_distinct: "refs_of h p rs \<Longrightarrow> distinct rs"
bulwahn@34051
   252
proof (induct rs arbitrary: p)
bulwahn@34051
   253
  case Nil thus ?case by simp
bulwahn@34051
   254
next
bulwahn@34051
   255
  case (Cons r rs')
bulwahn@34051
   256
  thus ?case
bulwahn@34051
   257
    by (cases p, auto simp add: refs_of_next)
bulwahn@34051
   258
qed
bulwahn@34051
   259
bulwahn@34051
   260
lemma refs_of'_distinct: "refs_of' h p rs \<Longrightarrow> distinct rs"
bulwahn@34051
   261
  unfolding refs_of'_def'
bulwahn@34051
   262
  by (fastsimp simp add: refs_of_distinct refs_of_next)
bulwahn@34051
   263
bulwahn@34051
   264
bulwahn@34051
   265
subsection {* Interaction of these predicates with our heap transitions *}
bulwahn@34051
   266
haftmann@37725
   267
lemma list_of_set_ref: "refs_of h q rs \<Longrightarrow> p \<notin> set rs \<Longrightarrow> list_of (Ref.set p v h) q as = list_of h q as"
bulwahn@34051
   268
using assms
bulwahn@34051
   269
proof (induct as arbitrary: q rs)
bulwahn@34051
   270
  case Nil thus ?case by simp
bulwahn@34051
   271
next
bulwahn@34051
   272
  case (Cons x xs)
bulwahn@34051
   273
  thus ?case
bulwahn@34051
   274
  proof (cases q)
bulwahn@34051
   275
    case Empty thus ?thesis by auto
bulwahn@34051
   276
  next
bulwahn@34051
   277
    case (Node a ref)
haftmann@37725
   278
    from Cons(2) Node obtain rs' where 1: "refs_of h (Ref.get h ref) rs'" and rs_rs': "rs = ref # rs'" by auto
bulwahn@34051
   279
    from Cons(3) rs_rs' have "ref \<noteq> p" by fastsimp
haftmann@37725
   280
    hence ref_eq: "Ref.get (Ref.set p v h) ref = (Ref.get h ref)" by (auto simp add: Ref.get_set_neq)
bulwahn@34051
   281
    from rs_rs' Cons(3) have 2: "p \<notin> set rs'" by simp
bulwahn@34051
   282
    from Cons.hyps[OF 1 2] Node ref_eq show ?thesis by simp
bulwahn@34051
   283
  qed
bulwahn@34051
   284
qed
bulwahn@34051
   285
haftmann@37725
   286
lemma refs_of_set_ref: "refs_of h q rs \<Longrightarrow> p \<notin> set rs \<Longrightarrow> refs_of (Ref.set p v h) q as = refs_of h q as"
bulwahn@34051
   287
proof (induct as arbitrary: q rs)
bulwahn@34051
   288
  case Nil thus ?case by simp
bulwahn@34051
   289
next
bulwahn@34051
   290
  case (Cons x xs)
bulwahn@34051
   291
  thus ?case
bulwahn@34051
   292
  proof (cases q)
bulwahn@34051
   293
    case Empty thus ?thesis by auto
bulwahn@34051
   294
  next
bulwahn@34051
   295
    case (Node a ref)
haftmann@37725
   296
    from Cons(2) Node obtain rs' where 1: "refs_of h (Ref.get h ref) rs'" and rs_rs': "rs = ref # rs'" by auto
bulwahn@34051
   297
    from Cons(3) rs_rs' have "ref \<noteq> p" by fastsimp
haftmann@37725
   298
    hence ref_eq: "Ref.get (Ref.set p v h) ref = (Ref.get h ref)" by (auto simp add: Ref.get_set_neq)
bulwahn@34051
   299
    from rs_rs' Cons(3) have 2: "p \<notin> set rs'" by simp
bulwahn@34051
   300
    from Cons.hyps[OF 1 2] Node ref_eq show ?thesis by auto
bulwahn@34051
   301
  qed
bulwahn@34051
   302
qed
bulwahn@34051
   303
haftmann@37725
   304
lemma refs_of_set_ref2: "refs_of (Ref.set p v h) q rs \<Longrightarrow> p \<notin> set rs \<Longrightarrow> refs_of (Ref.set p v h) q rs = refs_of h q rs"
bulwahn@34051
   305
proof (induct rs arbitrary: q)
bulwahn@34051
   306
  case Nil thus ?case by simp
bulwahn@34051
   307
next
bulwahn@34051
   308
  case (Cons x xs)
bulwahn@34051
   309
  thus ?case
bulwahn@34051
   310
  proof (cases q)
bulwahn@34051
   311
    case Empty thus ?thesis by auto
bulwahn@34051
   312
  next
bulwahn@34051
   313
    case (Node a ref)
haftmann@37725
   314
    from Cons(2) Node have 1:"refs_of (Ref.set p v h) (Ref.get (Ref.set p v h) ref) xs" and x_ref: "x = ref" by auto
bulwahn@34051
   315
    from Cons(3) this have "ref \<noteq> p" by fastsimp
haftmann@37725
   316
    hence ref_eq: "Ref.get (Ref.set p v h) ref = (Ref.get h ref)" by (auto simp add: Ref.get_set_neq)
bulwahn@34051
   317
    from Cons(3) have 2: "p \<notin> set xs" by simp
bulwahn@34051
   318
    with Cons.hyps 1 2 Node ref_eq show ?thesis
bulwahn@34051
   319
      by simp
bulwahn@34051
   320
  qed
bulwahn@34051
   321
qed
bulwahn@34051
   322
bulwahn@34051
   323
lemma list_of'_set_ref:
bulwahn@34051
   324
  assumes "refs_of' h q rs"
bulwahn@34051
   325
  assumes "p \<notin> set rs"
haftmann@37725
   326
  shows "list_of' (Ref.set p v h) q as = list_of' h q as"
bulwahn@34051
   327
proof -
bulwahn@34051
   328
  from assms have "q \<noteq> p" by (auto simp only: dest!: refs_of'E)
bulwahn@34051
   329
  with assms show ?thesis
bulwahn@34051
   330
    unfolding list_of'_def refs_of'_def'
bulwahn@34051
   331
    by (auto simp add: list_of_set_ref)
bulwahn@34051
   332
qed
bulwahn@34051
   333
bulwahn@34051
   334
lemma list_of'_set_next_ref_Node[simp]:
bulwahn@34051
   335
  assumes "list_of' h r xs"
haftmann@37725
   336
  assumes "Ref.get h p = Node x r'"
bulwahn@34051
   337
  assumes "refs_of' h r rs"
bulwahn@34051
   338
  assumes "p \<notin> set rs"
haftmann@37725
   339
  shows "list_of' (Ref.set p (Node x r) h) p (x#xs) = list_of' h r xs"
bulwahn@34051
   340
using assms
bulwahn@34051
   341
unfolding list_of'_def refs_of'_def'
haftmann@37725
   342
by (auto simp add: list_of_set_ref Ref.noteq_sym)
bulwahn@34051
   343
bulwahn@34051
   344
lemma refs_of'_set_ref:
bulwahn@34051
   345
  assumes "refs_of' h q rs"
bulwahn@34051
   346
  assumes "p \<notin> set rs"
haftmann@37725
   347
  shows "refs_of' (Ref.set p v h) q as = refs_of' h q as"
bulwahn@34051
   348
using assms
bulwahn@34051
   349
proof -
bulwahn@34051
   350
  from assms have "q \<noteq> p" by (auto simp only: dest!: refs_of'E)
bulwahn@34051
   351
  with assms show ?thesis
bulwahn@34051
   352
    unfolding refs_of'_def'
bulwahn@34051
   353
    by (auto simp add: refs_of_set_ref)
bulwahn@34051
   354
qed
bulwahn@34051
   355
bulwahn@34051
   356
lemma refs_of'_set_ref2:
haftmann@37725
   357
  assumes "refs_of' (Ref.set p v h) q rs"
bulwahn@34051
   358
  assumes "p \<notin> set rs"
haftmann@37725
   359
  shows "refs_of' (Ref.set p v h) q as = refs_of' h q as"
bulwahn@34051
   360
using assms
bulwahn@34051
   361
proof -
bulwahn@34051
   362
  from assms have "q \<noteq> p" by (auto simp only: dest!: refs_of'E)
bulwahn@34051
   363
  with assms show ?thesis
bulwahn@34051
   364
    unfolding refs_of'_def'
bulwahn@34051
   365
    apply auto
bulwahn@34051
   366
    apply (subgoal_tac "prs = prsa")
haftmann@37725
   367
    apply (insert refs_of_set_ref2[of p v h "Ref.get h q"])
bulwahn@34051
   368
    apply (erule_tac x="prs" in meta_allE)
bulwahn@34051
   369
    apply auto
bulwahn@34051
   370
    apply (auto dest: refs_of_is_fun)
bulwahn@34051
   371
    done
bulwahn@34051
   372
qed
bulwahn@34051
   373
bulwahn@34051
   374
lemma refs_of'_set_next_ref:
haftmann@37725
   375
assumes "Ref.get h1 p = Node x pn"
haftmann@37725
   376
assumes "refs_of' (Ref.set p (Node x r1) h1) p rs"
bulwahn@34051
   377
obtains r1s where "rs = (p#r1s)" and "refs_of' h1 r1 r1s"
bulwahn@34051
   378
using assms
bulwahn@34051
   379
proof -
bulwahn@34051
   380
  from assms refs_of'_distinct[OF assms(2)] have "\<exists> r1s. rs = (p # r1s) \<and> refs_of' h1 r1 r1s"
bulwahn@34051
   381
    apply -
bulwahn@34051
   382
    unfolding refs_of'_def'[of _ p]
haftmann@37725
   383
    apply (auto, frule refs_of_set_ref2) by (auto dest: Ref.noteq_sym)
bulwahn@34051
   384
  with prems show thesis by auto
bulwahn@34051
   385
qed
bulwahn@34051
   386
bulwahn@34051
   387
section {* Proving make_llist and traverse correct *}
bulwahn@34051
   388
bulwahn@34051
   389
lemma refs_of_invariant:
bulwahn@34051
   390
  assumes "refs_of h (r::('a::heap) node) xs"
haftmann@37725
   391
  assumes "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
bulwahn@34051
   392
  shows "refs_of h' r xs"
bulwahn@34051
   393
using assms
bulwahn@34051
   394
proof (induct xs arbitrary: r)
bulwahn@34051
   395
  case Nil thus ?case by simp
bulwahn@34051
   396
next
bulwahn@34051
   397
  case (Cons x xs')
bulwahn@34051
   398
  from Cons(2) obtain v where Node: "r = Node v x" by (cases r, auto)
haftmann@37725
   399
  from Cons(2) Node have refs_of_next: "refs_of h (Ref.get h x) xs'" by simp
haftmann@37725
   400
  from Cons(2-3) Node have ref_eq: "Ref.get h x = Ref.get h' x" by auto
haftmann@37725
   401
  from ref_eq refs_of_next have 1: "refs_of h (Ref.get h' x) xs'" by simp
haftmann@37725
   402
  from Cons(2) Cons(3) have "\<forall>ref \<in> set xs'. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref"
bulwahn@34051
   403
    by fastsimp
haftmann@37725
   404
  with Cons(3) 1 have 2: "\<forall>refs. refs_of h (Ref.get h' x) refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
bulwahn@34051
   405
    by (fastsimp dest: refs_of_is_fun)
haftmann@37725
   406
  from Cons.hyps[OF 1 2] have "refs_of h' (Ref.get h' x) xs'" .
bulwahn@34051
   407
  with Node show ?case by simp
bulwahn@34051
   408
qed
bulwahn@34051
   409
bulwahn@34051
   410
lemma refs_of'_invariant:
bulwahn@34051
   411
  assumes "refs_of' h r xs"
haftmann@37725
   412
  assumes "\<forall>refs. refs_of' h r refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
bulwahn@34051
   413
  shows "refs_of' h' r xs"
bulwahn@34051
   414
using assms
bulwahn@34051
   415
proof -
haftmann@37725
   416
  from assms obtain prs where refs:"refs_of h (Ref.get h r) prs" and xs_def: "xs = r # prs"
bulwahn@34051
   417
    unfolding refs_of'_def' by auto
haftmann@37725
   418
  from xs_def assms have x_eq: "Ref.get h r = Ref.get h' r" by fastsimp
haftmann@37725
   419
  from refs assms xs_def have 2: "\<forall>refs. refs_of h (Ref.get h r) refs \<longrightarrow>
haftmann@37725
   420
     (\<forall>ref\<in>set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)" 
bulwahn@34051
   421
    by (fastsimp dest: refs_of_is_fun)
bulwahn@34051
   422
  from refs_of_invariant [OF refs 2] xs_def x_eq show ?thesis
bulwahn@34051
   423
    unfolding refs_of'_def' by auto
bulwahn@34051
   424
qed
bulwahn@34051
   425
bulwahn@34051
   426
lemma list_of_invariant:
bulwahn@34051
   427
  assumes "list_of h (r::('a::heap) node) xs"
haftmann@37725
   428
  assumes "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
bulwahn@34051
   429
  shows "list_of h' r xs"
bulwahn@34051
   430
using assms
bulwahn@34051
   431
proof (induct xs arbitrary: r)
bulwahn@34051
   432
  case Nil thus ?case by simp
bulwahn@34051
   433
next
bulwahn@34051
   434
  case (Cons x xs')
bulwahn@34051
   435
bulwahn@34051
   436
  from Cons(2) obtain ref where Node: "r = Node x ref"
bulwahn@34051
   437
    by (cases r, auto)
bulwahn@34051
   438
  from Cons(2) obtain rs where rs_def: "refs_of h r rs" by (rule list_of_refs_of)
bulwahn@34051
   439
  from Node rs_def obtain rss where refs_of: "refs_of h r (ref#rss)" and rss_def: "rs = ref#rss" by auto
haftmann@37725
   440
  from Cons(3) Node refs_of have ref_eq: "Ref.get h ref = Ref.get h' ref"
bulwahn@34051
   441
    by auto
haftmann@37725
   442
  from Cons(2) ref_eq Node have 1: "list_of h (Ref.get h' ref) xs'" by simp
haftmann@37725
   443
  from refs_of Node ref_eq have refs_of_ref: "refs_of h (Ref.get h' ref) rss" by simp
haftmann@37725
   444
  from Cons(3) rs_def have rs_heap_eq: "\<forall>ref\<in>set rs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref" by simp
haftmann@37725
   445
  from refs_of_ref rs_heap_eq rss_def have 2: "\<forall>refs. refs_of h (Ref.get h' ref) refs \<longrightarrow>
haftmann@37725
   446
          (\<forall>ref\<in>set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
bulwahn@34051
   447
    by (auto dest: refs_of_is_fun)
bulwahn@34051
   448
  from Cons(1)[OF 1 2]
haftmann@37725
   449
  have "list_of h' (Ref.get h' ref) xs'" .
bulwahn@34051
   450
  with Node show ?case
bulwahn@34051
   451
    unfolding list_of'_def
bulwahn@34051
   452
    by simp
bulwahn@34051
   453
qed
bulwahn@34051
   454
haftmann@37771
   455
lemma crel_ref:
haftmann@37771
   456
  assumes "crel (ref v) h h' x"
haftmann@37771
   457
  obtains "Ref.get h' x = v"
haftmann@37771
   458
  and "\<not> Ref.present h x"
haftmann@37771
   459
  and "Ref.present h' x"
haftmann@37771
   460
  and "\<forall>y. Ref.present h y \<longrightarrow> Ref.get h y = Ref.get h' y"
haftmann@37771
   461
 (* and "lim h' = Suc (lim h)" *)
haftmann@37771
   462
  and "\<forall>y. Ref.present h y \<longrightarrow> Ref.present h' y"
haftmann@37771
   463
  using assms
haftmann@37771
   464
  unfolding Ref.ref_def
haftmann@37771
   465
  apply (elim crel_heapE)
haftmann@37771
   466
  unfolding Ref.alloc_def
haftmann@37771
   467
  apply (simp add: Let_def)
haftmann@37771
   468
  unfolding Ref.present_def
haftmann@37771
   469
  apply auto
haftmann@37771
   470
  unfolding Ref.get_def Ref.set_def
haftmann@37771
   471
  apply auto
haftmann@37771
   472
  done
haftmann@37771
   473
bulwahn@34051
   474
lemma make_llist:
bulwahn@34051
   475
assumes "crel (make_llist xs) h h' r"
haftmann@37725
   476
shows "list_of h' r xs \<and> (\<forall>rs. refs_of h' r rs \<longrightarrow> (\<forall>ref \<in> (set rs). Ref.present h' ref))"
bulwahn@34051
   477
using assms 
bulwahn@34051
   478
proof (induct xs arbitrary: h h' r)
haftmann@37771
   479
  case Nil thus ?case by (auto elim: crel_returnE simp add: make_llist.simps)
bulwahn@34051
   480
next
bulwahn@34051
   481
  case (Cons x xs')
bulwahn@34051
   482
  from Cons.prems obtain h1 r1 r' where make_llist: "crel (make_llist xs') h h1 r1"
haftmann@37725
   483
    and crel_refnew:"crel (ref r1) h1 h' r'" and Node: "r = Node x r'"
bulwahn@34051
   484
    unfolding make_llist.simps
haftmann@37771
   485
    by (auto elim!: crel_bindE crel_returnE)
bulwahn@34051
   486
  from Cons.hyps[OF make_llist] have list_of_h1: "list_of h1 r1 xs'" ..
bulwahn@34051
   487
  from Cons.hyps[OF make_llist] obtain rs' where rs'_def: "refs_of h1 r1 rs'" by (auto intro: list_of_refs_of)
haftmann@37725
   488
  from Cons.hyps[OF make_llist] rs'_def have refs_present: "\<forall>ref\<in>set rs'. Ref.present h1 ref" by simp
bulwahn@34051
   489
  from crel_refnew rs'_def refs_present have refs_unchanged: "\<forall>refs. refs_of h1 r1 refs \<longrightarrow>
haftmann@37725
   490
         (\<forall>ref\<in>set refs. Ref.present h1 ref \<and> Ref.present h' ref \<and> Ref.get h1 ref = Ref.get h' ref)"
haftmann@37725
   491
    by (auto elim!: crel_ref dest: refs_of_is_fun)
bulwahn@34051
   492
  with list_of_invariant[OF list_of_h1 refs_unchanged] Node crel_refnew have fstgoal: "list_of h' r (x # xs')"
bulwahn@34051
   493
    unfolding list_of.simps
haftmann@37771
   494
    by (auto elim!: crel_refE)
haftmann@37725
   495
  from refs_unchanged rs'_def have refs_still_present: "\<forall>ref\<in>set rs'. Ref.present h' ref" by auto
bulwahn@34051
   496
  from refs_of_invariant[OF rs'_def refs_unchanged] refs_unchanged Node crel_refnew refs_still_present
haftmann@37725
   497
  have sndgoal: "\<forall>rs. refs_of h' r rs \<longrightarrow> (\<forall>ref\<in>set rs. Ref.present h' ref)"
haftmann@37771
   498
    by (fastsimp elim!: crel_refE dest: refs_of_is_fun)
bulwahn@34051
   499
  from fstgoal sndgoal show ?case ..
bulwahn@34051
   500
qed
bulwahn@34051
   501
bulwahn@34051
   502
lemma traverse: "list_of h n r \<Longrightarrow> crel (traverse n) h h r"
bulwahn@34051
   503
proof (induct r arbitrary: n)
bulwahn@34051
   504
  case Nil
bulwahn@34051
   505
  thus ?case
bulwahn@34051
   506
    by (auto intro: crel_returnI)
bulwahn@34051
   507
next
bulwahn@34051
   508
  case (Cons x xs)
bulwahn@34051
   509
  thus ?case
bulwahn@34051
   510
  apply (cases n, auto)
haftmann@37771
   511
  by (auto intro!: crel_bindI crel_returnI crel_lookupI)
bulwahn@34051
   512
qed
bulwahn@34051
   513
bulwahn@34051
   514
lemma traverse_make_llist':
bulwahn@34051
   515
  assumes crel: "crel (make_llist xs \<guillemotright>= traverse) h h' r"
bulwahn@34051
   516
  shows "r = xs"
bulwahn@34051
   517
proof -
bulwahn@34051
   518
  from crel obtain h1 r1
bulwahn@34051
   519
    where makell: "crel (make_llist xs) h h1 r1"
bulwahn@34051
   520
    and trav: "crel (traverse r1) h1 h' r"
haftmann@37771
   521
    by (auto elim!: crel_bindE)
bulwahn@34051
   522
  from make_llist[OF makell] have "list_of h1 r1 xs" ..
bulwahn@34051
   523
  from traverse [OF this] trav show ?thesis
bulwahn@34051
   524
    using crel_deterministic by fastsimp
bulwahn@34051
   525
qed
bulwahn@34051
   526
bulwahn@34051
   527
section {* Proving correctness of in-place reversal *}
bulwahn@34051
   528
bulwahn@34051
   529
subsection {* Definition of in-place reversal *}
bulwahn@34051
   530
bulwahn@34051
   531
definition rev' :: "(('a::heap) node ref \<times> 'a node ref) \<Rightarrow> 'a node ref Heap"
krauss@37792
   532
where "rev' = MREC (\<lambda>(q, p). do { v \<leftarrow> !p; (case v of Empty \<Rightarrow> (return (Inl q))
krauss@37792
   533
                            | Node x next \<Rightarrow> do {
bulwahn@34051
   534
                                    p := Node x q;
bulwahn@34051
   535
                                    return (Inr (p, next))
krauss@37792
   536
                                  })})
bulwahn@34051
   537
             (\<lambda>x s z. return z)"
bulwahn@34051
   538
bulwahn@34051
   539
lemma rev'_simps [code]:
bulwahn@34051
   540
  "rev' (q, p) =
krauss@37792
   541
   do {
bulwahn@34051
   542
     v \<leftarrow> !p;
bulwahn@34051
   543
     (case v of
bulwahn@34051
   544
        Empty \<Rightarrow> return q
bulwahn@34051
   545
      | Node x next \<Rightarrow>
krauss@37792
   546
        do {
bulwahn@34051
   547
          p := Node x q;
bulwahn@34051
   548
          rev' (p, next)
krauss@37792
   549
        })
krauss@37792
   550
  }"
bulwahn@34051
   551
  unfolding rev'_def MREC_rule[of _ _ "(q, p)"] unfolding rev'_def[symmetric]
bulwahn@34051
   552
thm arg_cong2
haftmann@37828
   553
  by (auto simp add: expand_fun_eq intro: arg_cong2[where f = bind] split: node.split)
bulwahn@34051
   554
haftmann@37725
   555
primrec rev :: "('a:: heap) node \<Rightarrow> 'a node Heap" 
bulwahn@34051
   556
where
bulwahn@34051
   557
  "rev Empty = return Empty"
krauss@37792
   558
| "rev (Node x n) = do { q \<leftarrow> ref Empty; p \<leftarrow> ref (Node x n); v \<leftarrow> rev' (q, p); !v }"
bulwahn@34051
   559
bulwahn@34051
   560
subsection {* Correctness Proof *}
bulwahn@34051
   561
bulwahn@34051
   562
lemma rev'_invariant:
bulwahn@34051
   563
  assumes "crel (rev' (q, p)) h h' v"
bulwahn@34051
   564
  assumes "list_of' h q qs"
bulwahn@34051
   565
  assumes "list_of' h p ps"
bulwahn@34051
   566
  assumes "\<forall>qrs prs. refs_of' h q qrs \<and> refs_of' h p prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   567
  shows "\<exists>vs. list_of' h' v vs \<and> vs = (List.rev ps) @ qs"
bulwahn@34051
   568
using assms
bulwahn@34051
   569
proof (induct ps arbitrary: qs p q h)
bulwahn@34051
   570
  case Nil
bulwahn@34051
   571
  thus ?case
bulwahn@34051
   572
    unfolding rev'_simps[of q p] list_of'_def
haftmann@37771
   573
    by (auto elim!: crel_bindE crel_lookupE crel_returnE)
bulwahn@34051
   574
next
bulwahn@34051
   575
  case (Cons x xs)
bulwahn@34051
   576
  (*"LinkedList.list_of h' (get_ref v h') (List.rev xs @ x # qsa)"*)
bulwahn@34051
   577
  from Cons(4) obtain ref where 
haftmann@37725
   578
    p_is_Node: "Ref.get h p = Node x ref"
bulwahn@34051
   579
    (*and "ref_present ref h"*)
bulwahn@34051
   580
    and list_of'_ref: "list_of' h ref xs"
haftmann@37725
   581
    unfolding list_of'_def by (cases "Ref.get h p", auto)
haftmann@37725
   582
  from p_is_Node Cons(2) have crel_rev': "crel (rev' (p, ref)) (Ref.set p (Node x q) h) h' v"
haftmann@37771
   583
    by (auto simp add: rev'_simps [of q p] elim!: crel_bindE crel_lookupE crel_updateE)
bulwahn@34051
   584
  from Cons(3) obtain qrs where qrs_def: "refs_of' h q qrs" by (elim list_of'_refs_of')
bulwahn@34051
   585
  from Cons(4) obtain prs where prs_def: "refs_of' h p prs" by (elim list_of'_refs_of')
bulwahn@34051
   586
  from qrs_def prs_def Cons(5) have distinct_pointers: "set qrs \<inter> set prs = {}" by fastsimp
bulwahn@34051
   587
  from qrs_def prs_def distinct_pointers refs_of'E have p_notin_qrs: "p \<notin> set qrs" by fastsimp
haftmann@37725
   588
  from Cons(3) qrs_def this have 1: "list_of' (Ref.set p (Node x q) h) p (x#qs)"
bulwahn@34051
   589
    unfolding list_of'_def  
bulwahn@34051
   590
    apply (simp)
bulwahn@34051
   591
    unfolding list_of'_def[symmetric]
bulwahn@34051
   592
    by (simp add: list_of'_set_ref)
bulwahn@34051
   593
  from list_of'_refs_of'2[OF Cons(4)] p_is_Node prs_def obtain refs where refs_def: "refs_of' h ref refs" and prs_refs: "prs = p # refs"
bulwahn@34051
   594
    unfolding refs_of'_def' by auto
bulwahn@34051
   595
  from prs_refs prs_def have p_not_in_refs: "p \<notin> set refs"
bulwahn@34051
   596
    by (fastsimp dest!: refs_of'_distinct)
haftmann@37725
   597
  with refs_def p_is_Node list_of'_ref have 2: "list_of' (Ref.set p (Node x q) h) ref xs"
bulwahn@34051
   598
    by (auto simp add: list_of'_set_ref)
haftmann@37725
   599
  from p_notin_qrs qrs_def have refs_of1: "refs_of' (Ref.set p (Node x q) h) p (p#qrs)"
bulwahn@34051
   600
    unfolding refs_of'_def'
bulwahn@34051
   601
    apply (simp)
bulwahn@34051
   602
    unfolding refs_of'_def'[symmetric]
bulwahn@34051
   603
    by (simp add: refs_of'_set_ref)
haftmann@37725
   604
  from p_not_in_refs p_is_Node refs_def have refs_of2: "refs_of' (Ref.set p (Node x q) h) ref refs"
bulwahn@34051
   605
    by (simp add: refs_of'_set_ref)
haftmann@37725
   606
  from p_not_in_refs refs_of1 refs_of2 distinct_pointers prs_refs have 3: "\<forall>qrs prs. refs_of' (Ref.set p (Node x q) h) p qrs \<and> refs_of' (Ref.set p (Node x q) h) ref prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   607
    apply - apply (rule allI)+ apply (rule impI) apply (erule conjE)
bulwahn@34051
   608
    apply (drule refs_of'_is_fun) back back apply assumption
bulwahn@34051
   609
    apply (drule refs_of'_is_fun) back back apply assumption
bulwahn@34051
   610
    apply auto done
bulwahn@34051
   611
  from Cons.hyps [OF crel_rev' 1 2 3] show ?case by simp
bulwahn@34051
   612
qed
bulwahn@34051
   613
bulwahn@34051
   614
bulwahn@34051
   615
lemma rev_correctness:
bulwahn@34051
   616
  assumes list_of_h: "list_of h r xs"
haftmann@37725
   617
  assumes validHeap: "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>r \<in> set refs. Ref.present h r)"
bulwahn@34051
   618
  assumes crel_rev: "crel (rev r) h h' r'"
bulwahn@34051
   619
  shows "list_of h' r' (List.rev xs)"
bulwahn@34051
   620
using assms
bulwahn@34051
   621
proof (cases r)
bulwahn@34051
   622
  case Empty
bulwahn@34051
   623
  with list_of_h crel_rev show ?thesis
haftmann@37771
   624
    by (auto simp add: list_of_Empty elim!: crel_returnE)
bulwahn@34051
   625
next
bulwahn@34051
   626
  case (Node x ps)
bulwahn@34051
   627
  with crel_rev obtain p q h1 h2 h3 v where
haftmann@37725
   628
    init: "crel (ref Empty) h h1 q"
haftmann@37725
   629
    "crel (ref (Node x ps)) h1 h2 p"
bulwahn@34051
   630
    and crel_rev':"crel (rev' (q, p)) h2 h3 v"
bulwahn@34051
   631
    and lookup: "crel (!v) h3 h' r'"
bulwahn@34051
   632
    using rev.simps
haftmann@37771
   633
    by (auto elim!: crel_bindE)
bulwahn@34051
   634
  from init have a1:"list_of' h2 q []"
bulwahn@34051
   635
    unfolding list_of'_def
haftmann@37725
   636
    by (auto elim!: crel_ref)
bulwahn@34051
   637
  from list_of_h obtain refs where refs_def: "refs_of h r refs" by (rule list_of_refs_of)
haftmann@37725
   638
  from validHeap init refs_def have heap_eq: "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>ref\<in>set refs. Ref.present h ref \<and> Ref.present h2 ref \<and> Ref.get h ref = Ref.get h2 ref)"
haftmann@37725
   639
    by (fastsimp elim!: crel_ref dest: refs_of_is_fun)
bulwahn@34051
   640
  from list_of_invariant[OF list_of_h heap_eq] have "list_of h2 r xs" .
bulwahn@34051
   641
  from init this Node have a2: "list_of' h2 p xs"
bulwahn@34051
   642
    apply -
bulwahn@34051
   643
    unfolding list_of'_def
haftmann@37771
   644
    apply (auto elim!: crel_refE)
bulwahn@34051
   645
    done
bulwahn@34051
   646
  from init have refs_of_q: "refs_of' h2 q [q]"
haftmann@37725
   647
    by (auto elim!: crel_ref)
bulwahn@34051
   648
  from refs_def Node have refs_of'_ps: "refs_of' h ps refs"
bulwahn@34051
   649
    by (auto simp add: refs_of'_def'[symmetric])
haftmann@37725
   650
  from validHeap refs_def have all_ref_present: "\<forall>r\<in>set refs. Ref.present h r" by simp
haftmann@37725
   651
  from init refs_of'_ps Node this have heap_eq: "\<forall>refs. refs_of' h ps refs \<longrightarrow> (\<forall>ref\<in>set refs. Ref.present h ref \<and> Ref.present h2 ref \<and> Ref.get h ref = Ref.get h2 ref)"
haftmann@37725
   652
    by (fastsimp elim!: crel_ref dest: refs_of'_is_fun)
bulwahn@34051
   653
  from refs_of'_invariant[OF refs_of'_ps this] have "refs_of' h2 ps refs" .
bulwahn@34051
   654
  with init have refs_of_p: "refs_of' h2 p (p#refs)"
haftmann@37771
   655
    by (auto elim!: crel_refE simp add: refs_of'_def')
bulwahn@34051
   656
  with init all_ref_present have q_is_new: "q \<notin> set (p#refs)"
haftmann@37771
   657
    by (auto elim!: crel_refE intro!: Ref.noteq_I)
bulwahn@34051
   658
  from refs_of_p refs_of_q q_is_new have a3: "\<forall>qrs prs. refs_of' h2 q qrs \<and> refs_of' h2 p prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   659
    by (fastsimp simp only: set.simps dest: refs_of'_is_fun)
haftmann@37725
   660
  from rev'_invariant [OF crel_rev' a1 a2 a3] have "list_of h3 (Ref.get h3 v) (List.rev xs)" 
bulwahn@34051
   661
    unfolding list_of'_def by auto
bulwahn@34051
   662
  with lookup show ?thesis
haftmann@37771
   663
    by (auto elim: crel_lookupE)
bulwahn@34051
   664
qed
bulwahn@34051
   665
bulwahn@34051
   666
bulwahn@34051
   667
section {* The merge function on Linked Lists *}
bulwahn@34051
   668
text {* We also prove merge correct *}
bulwahn@34051
   669
bulwahn@34051
   670
text{* First, we define merge on lists in a natural way. *}
bulwahn@34051
   671
bulwahn@34051
   672
fun Lmerge :: "('a::ord) list \<Rightarrow> 'a list \<Rightarrow> 'a list"
bulwahn@34051
   673
where
bulwahn@34051
   674
  "Lmerge (x#xs) (y#ys) =
bulwahn@34051
   675
     (if x \<le> y then x # Lmerge xs (y#ys) else y # Lmerge (x#xs) ys)"
bulwahn@34051
   676
| "Lmerge [] ys = ys"
bulwahn@34051
   677
| "Lmerge xs [] = xs"
bulwahn@34051
   678
bulwahn@34051
   679
subsection {* Definition of merge function *}
bulwahn@34051
   680
bulwahn@34051
   681
definition merge' :: "(('a::{heap, ord}) node ref * ('a::{heap, ord})) * ('a::{heap, ord}) node ref * ('a::{heap, ord}) node ref \<Rightarrow> ('a::{heap, ord}) node ref Heap"
bulwahn@34051
   682
where
krauss@37792
   683
"merge' = MREC (\<lambda>(_, p, q). do { v \<leftarrow> !p; w \<leftarrow> !q;
bulwahn@34051
   684
  (case v of Empty \<Rightarrow> return (Inl q)
bulwahn@34051
   685
          | Node valp np \<Rightarrow>
bulwahn@34051
   686
            (case w of Empty \<Rightarrow> return (Inl p)
bulwahn@34051
   687
                     | Node valq nq \<Rightarrow>
bulwahn@34051
   688
                       if (valp \<le> valq) then
bulwahn@34051
   689
                         return (Inr ((p, valp), np, q))
bulwahn@34051
   690
                       else
krauss@37792
   691
                         return (Inr ((q, valq), p, nq)))) })
krauss@37792
   692
 (\<lambda> _ ((n, v), _, _) r. do { n := Node v r; return n })"
bulwahn@34051
   693
bulwahn@34051
   694
definition merge where "merge p q = merge' (undefined, p, q)"
bulwahn@34051
   695
bulwahn@34051
   696
lemma if_return: "(if P then return x else return y) = return (if P then x else y)"
bulwahn@34051
   697
by auto
bulwahn@34051
   698
bulwahn@34051
   699
lemma if_distrib_App: "(if P then f else g) x = (if P then f x else g x)"
bulwahn@34051
   700
by auto
bulwahn@34051
   701
lemma redundant_if: "(if P then (if P then x else z) else y) = (if P then x else y)"
bulwahn@34051
   702
  "(if P then x else (if P then z else y)) = (if P then x else y)"
bulwahn@34051
   703
by auto
bulwahn@34051
   704
bulwahn@34051
   705
bulwahn@34051
   706
bulwahn@34051
   707
lemma sum_distrib: "sum_case fl fr (case x of Empty \<Rightarrow> y | Node v n \<Rightarrow> (z v n)) = (case x of Empty \<Rightarrow> sum_case fl fr y | Node v n \<Rightarrow> sum_case fl fr (z v n))"
bulwahn@34051
   708
by (cases x) auto
bulwahn@34051
   709
bulwahn@34051
   710
lemma merge: "merge' (x, p, q) = merge p q"
bulwahn@34051
   711
unfolding merge'_def merge_def
bulwahn@34051
   712
apply (simp add: MREC_rule) done
bulwahn@34051
   713
term "Ref.change"
bulwahn@34051
   714
lemma merge_simps [code]:
bulwahn@34051
   715
shows "merge p q =
krauss@37792
   716
do { v \<leftarrow> !p;
bulwahn@34051
   717
   w \<leftarrow> !q;
bulwahn@34051
   718
   (case v of node.Empty \<Rightarrow> return q
bulwahn@34051
   719
    | Node valp np \<Rightarrow>
bulwahn@34051
   720
        case w of node.Empty \<Rightarrow> return p
bulwahn@34051
   721
        | Node valq nq \<Rightarrow>
krauss@37792
   722
            if valp \<le> valq then do { r \<leftarrow> merge np q;
bulwahn@34051
   723
                                   p := (Node valp r);
bulwahn@34051
   724
                                   return p
krauss@37792
   725
                                }
krauss@37792
   726
            else do { r \<leftarrow> merge p nq;
bulwahn@34051
   727
                    q := (Node valq r);
bulwahn@34051
   728
                    return q
krauss@37792
   729
                 })
krauss@37792
   730
}"
bulwahn@34051
   731
proof -
bulwahn@34051
   732
  {fix v x y
bulwahn@34051
   733
    have case_return: "(case v of Empty \<Rightarrow> return x | Node v n \<Rightarrow> return (y v n)) = return (case v of Empty \<Rightarrow> x | Node v n \<Rightarrow> y v n)" by (cases v) auto
bulwahn@34051
   734
    } note case_return = this
bulwahn@34051
   735
show ?thesis
bulwahn@34051
   736
unfolding merge_def[of p q] merge'_def
bulwahn@34051
   737
apply (simp add: MREC_rule[of _ _ "(undefined, p, q)"])
bulwahn@34051
   738
unfolding bind_bind return_bind
bulwahn@34051
   739
unfolding merge'_def[symmetric]
bulwahn@34051
   740
unfolding if_return case_return bind_bind return_bind sum_distrib sum.cases
bulwahn@34051
   741
unfolding if_distrib[symmetric, where f="Inr"]
bulwahn@34051
   742
unfolding sum.cases
bulwahn@34051
   743
unfolding if_distrib
bulwahn@34051
   744
unfolding split_beta fst_conv snd_conv
bulwahn@34051
   745
unfolding if_distrib_App redundant_if merge
bulwahn@34051
   746
..
bulwahn@34051
   747
qed
bulwahn@34051
   748
bulwahn@34051
   749
subsection {* Induction refinement by applying the abstraction function to our induct rule *}
bulwahn@34051
   750
bulwahn@34051
   751
text {* From our original induction rule Lmerge.induct, we derive a new rule with our list_of' predicate *}
bulwahn@34051
   752
bulwahn@34051
   753
lemma merge_induct2:
bulwahn@34051
   754
  assumes "list_of' h (p::'a::{heap, ord} node ref) xs"
bulwahn@34051
   755
  assumes "list_of' h q ys"
haftmann@37725
   756
  assumes "\<And> ys p q. \<lbrakk> list_of' h p []; list_of' h q ys; Ref.get h p = Empty \<rbrakk> \<Longrightarrow> P p q [] ys"
haftmann@37725
   757
  assumes "\<And> x xs' p q pn. \<lbrakk> list_of' h p (x#xs'); list_of' h q []; Ref.get h p = Node x pn; Ref.get h q = Empty \<rbrakk> \<Longrightarrow> P p q (x#xs') []"
bulwahn@34051
   758
  assumes "\<And> x xs' y ys' p q pn qn.
haftmann@37725
   759
  \<lbrakk> list_of' h p (x#xs'); list_of' h q (y#ys'); Ref.get h p = Node x pn; Ref.get h q = Node y qn;
bulwahn@34051
   760
  x \<le> y; P pn q xs' (y#ys') \<rbrakk>
bulwahn@34051
   761
  \<Longrightarrow> P p q (x#xs') (y#ys')"
bulwahn@34051
   762
  assumes "\<And> x xs' y ys' p q pn qn.
haftmann@37725
   763
  \<lbrakk> list_of' h p (x#xs'); list_of' h q (y#ys'); Ref.get h p = Node x pn; Ref.get h q = Node y qn;
bulwahn@34051
   764
  \<not> x \<le> y; P p qn (x#xs') ys'\<rbrakk>
bulwahn@34051
   765
  \<Longrightarrow> P p q (x#xs') (y#ys')"
bulwahn@34051
   766
  shows "P p q xs ys"
bulwahn@34051
   767
using assms(1-2)
bulwahn@34051
   768
proof (induct xs ys arbitrary: p q rule: Lmerge.induct)
bulwahn@34051
   769
  case (2 ys)
haftmann@37725
   770
  from 2(1) have "Ref.get h p = Empty" unfolding list_of'_def by simp
bulwahn@34051
   771
  with 2(1-2) assms(3) show ?case by blast
bulwahn@34051
   772
next
bulwahn@34051
   773
  case (3 x xs')
haftmann@37725
   774
  from 3(1) obtain pn where Node: "Ref.get h p = Node x pn" by (rule list_of'_Cons)
haftmann@37725
   775
  from 3(2) have "Ref.get h q = Empty" unfolding list_of'_def by simp
bulwahn@34051
   776
  with Node 3(1-2) assms(4) show ?case by blast
bulwahn@34051
   777
next
bulwahn@34051
   778
  case (1 x xs' y ys')
haftmann@37725
   779
  from 1(3) obtain pn where pNode:"Ref.get h p = Node x pn"
bulwahn@34051
   780
    and list_of'_pn: "list_of' h pn xs'" by (rule list_of'_Cons)
haftmann@37725
   781
  from 1(4) obtain qn where qNode:"Ref.get h q = Node y qn"
bulwahn@34051
   782
    and  list_of'_qn: "list_of' h qn ys'" by (rule list_of'_Cons)
bulwahn@34051
   783
  show ?case
bulwahn@34051
   784
  proof (cases "x \<le> y")
bulwahn@34051
   785
    case True
bulwahn@34051
   786
    from 1(1)[OF True list_of'_pn 1(4)] assms(5) 1(3-4) pNode qNode True
bulwahn@34051
   787
    show ?thesis by blast
bulwahn@34051
   788
  next
bulwahn@34051
   789
    case False
bulwahn@34051
   790
    from 1(2)[OF False 1(3) list_of'_qn] assms(6) 1(3-4) pNode qNode False
bulwahn@34051
   791
    show ?thesis by blast
bulwahn@34051
   792
  qed
bulwahn@34051
   793
qed
bulwahn@34051
   794
bulwahn@34051
   795
bulwahn@34051
   796
text {* secondly, we add the crel statement in the premise, and derive the crel statements for the single cases which we then eliminate with our crel elim rules. *}
bulwahn@34051
   797
  
bulwahn@34051
   798
lemma merge_induct3: 
bulwahn@34051
   799
assumes  "list_of' h p xs"
bulwahn@34051
   800
assumes  "list_of' h q ys"
bulwahn@34051
   801
assumes  "crel (merge p q) h h' r"
haftmann@37725
   802
assumes  "\<And> ys p q. \<lbrakk> list_of' h p []; list_of' h q ys; Ref.get h p = Empty \<rbrakk> \<Longrightarrow> P p q h h q [] ys"
haftmann@37725
   803
assumes  "\<And> x xs' p q pn. \<lbrakk> list_of' h p (x#xs'); list_of' h q []; Ref.get h p = Node x pn; Ref.get h q = Empty \<rbrakk> \<Longrightarrow> P p q h h p (x#xs') []"
bulwahn@34051
   804
assumes  "\<And> x xs' y ys' p q pn qn h1 r1 h'.
haftmann@37725
   805
  \<lbrakk> list_of' h p (x#xs'); list_of' h q (y#ys');Ref.get h p = Node x pn; Ref.get h q = Node y qn;
haftmann@37725
   806
  x \<le> y; crel (merge pn q) h h1 r1 ; P pn q h h1 r1 xs' (y#ys'); h' = Ref.set p (Node x r1) h1 \<rbrakk>
bulwahn@34051
   807
  \<Longrightarrow> P p q h h' p (x#xs') (y#ys')"
bulwahn@34051
   808
assumes "\<And> x xs' y ys' p q pn qn h1 r1 h'.
haftmann@37725
   809
  \<lbrakk> list_of' h p (x#xs'); list_of' h q (y#ys'); Ref.get h p = Node x pn; Ref.get h q = Node y qn;
haftmann@37725
   810
  \<not> x \<le> y; crel (merge p qn) h h1 r1; P p qn h h1 r1 (x#xs') ys'; h' = Ref.set q (Node y r1) h1 \<rbrakk>
bulwahn@34051
   811
  \<Longrightarrow> P p q h h' q (x#xs') (y#ys')"
bulwahn@34051
   812
shows "P p q h h' r xs ys"
bulwahn@34051
   813
using assms(3)
bulwahn@34051
   814
proof (induct arbitrary: h' r rule: merge_induct2[OF assms(1) assms(2)])
bulwahn@34051
   815
  case (1 ys p q)
bulwahn@34051
   816
  from 1(3-4) have "h = h' \<and> r = q"
bulwahn@34051
   817
    unfolding merge_simps[of p q]
haftmann@37771
   818
    by (auto elim!: crel_lookupE crel_bindE crel_returnE)
bulwahn@34051
   819
  with assms(4)[OF 1(1) 1(2) 1(3)] show ?case by simp
bulwahn@34051
   820
next
bulwahn@34051
   821
  case (2 x xs' p q pn)
bulwahn@34051
   822
  from 2(3-5) have "h = h' \<and> r = p"
bulwahn@34051
   823
    unfolding merge_simps[of p q]
haftmann@37771
   824
    by (auto elim!: crel_lookupE crel_bindE crel_returnE)
bulwahn@34051
   825
  with assms(5)[OF 2(1-4)] show ?case by simp
bulwahn@34051
   826
next
bulwahn@34051
   827
  case (3 x xs' y ys' p q pn qn)
bulwahn@34051
   828
  from 3(3-5) 3(7) obtain h1 r1 where
bulwahn@34051
   829
    1: "crel (merge pn q) h h1 r1" 
haftmann@37725
   830
    and 2: "h' = Ref.set p (Node x r1) h1 \<and> r = p"
bulwahn@34051
   831
    unfolding merge_simps[of p q]
haftmann@37771
   832
    by (auto elim!: crel_lookupE crel_bindE crel_returnE crel_ifE crel_updateE)
bulwahn@34051
   833
  from 3(6)[OF 1] assms(6) [OF 3(1-5)] 1 2 show ?case by simp
bulwahn@34051
   834
next
bulwahn@34051
   835
  case (4 x xs' y ys' p q pn qn)
bulwahn@34051
   836
  from 4(3-5) 4(7) obtain h1 r1 where
bulwahn@34051
   837
    1: "crel (merge p qn) h h1 r1" 
haftmann@37725
   838
    and 2: "h' = Ref.set q (Node y r1) h1 \<and> r = q"
bulwahn@34051
   839
    unfolding merge_simps[of p q]
haftmann@37771
   840
    by (auto elim!: crel_lookupE crel_bindE crel_returnE crel_ifE crel_updateE)
bulwahn@34051
   841
  from 4(6)[OF 1] assms(7) [OF 4(1-5)] 1 2 show ?case by simp
bulwahn@34051
   842
qed
bulwahn@34051
   843
bulwahn@34051
   844
bulwahn@34051
   845
subsection {* Proving merge correct *}
bulwahn@34051
   846
bulwahn@34051
   847
text {* As many parts of the following three proofs are identical, we could actually move the
bulwahn@34051
   848
same reasoning into an extended induction rule *}
bulwahn@34051
   849
 
bulwahn@34051
   850
lemma merge_unchanged:
bulwahn@34051
   851
  assumes "refs_of' h p xs"
bulwahn@34051
   852
  assumes "refs_of' h q ys"  
bulwahn@34051
   853
  assumes "crel (merge p q) h h' r'"
bulwahn@34051
   854
  assumes "set xs \<inter> set ys = {}"
bulwahn@34051
   855
  assumes "r \<notin> set xs \<union> set ys"
haftmann@37725
   856
  shows "Ref.get h r = Ref.get h' r"
bulwahn@34051
   857
proof -
bulwahn@34051
   858
  from assms(1) obtain ps where ps_def: "list_of' h p ps" by (rule refs_of'_list_of')
bulwahn@34051
   859
  from assms(2) obtain qs where qs_def: "list_of' h q qs" by (rule refs_of'_list_of')
bulwahn@34051
   860
  show ?thesis using assms(1) assms(2) assms(4) assms(5)
bulwahn@34051
   861
  proof (induct arbitrary: xs ys r rule: merge_induct3[OF ps_def qs_def assms(3)])
bulwahn@34051
   862
    case 1 thus ?case by simp
bulwahn@34051
   863
  next
bulwahn@34051
   864
    case 2 thus ?case by simp
bulwahn@34051
   865
  next
bulwahn@34051
   866
    case (3 x xs' y ys' p q pn qn h1 r1 h' xs ys r)
bulwahn@34051
   867
    from 3(9) 3(3) obtain pnrs
bulwahn@34051
   868
      where pnrs_def: "xs = p#pnrs"
bulwahn@34051
   869
      and refs_of'_pn: "refs_of' h pn pnrs"
bulwahn@34051
   870
      by (rule refs_of'_Node)
bulwahn@34051
   871
    with 3(12) have r_in: "r \<notin> set pnrs \<union> set ys" by auto
bulwahn@34051
   872
    from pnrs_def 3(12) have "r \<noteq> p" by auto
bulwahn@34051
   873
    with 3(11) 3(12) pnrs_def refs_of'_distinct[OF 3(9)] have p_in: "p \<notin> set pnrs \<union> set ys" by auto
bulwahn@34051
   874
    from 3(11) pnrs_def have no_inter: "set pnrs \<inter> set ys = {}" by auto
haftmann@37725
   875
    from 3(7)[OF refs_of'_pn 3(10) this p_in] 3(3) have p_is_Node: "Ref.get h1 p = Node x pn"
haftmann@37725
   876
      by simp
bulwahn@34051
   877
    from 3(7)[OF refs_of'_pn 3(10) no_inter r_in] 3(8) `r \<noteq> p` show ?case
bulwahn@34051
   878
      by simp
bulwahn@34051
   879
  next
bulwahn@34051
   880
    case (4 x xs' y ys' p q pn qn h1 r1 h' xs ys r)
bulwahn@34051
   881
    from 4(10) 4(4) obtain qnrs
bulwahn@34051
   882
      where qnrs_def: "ys = q#qnrs"
bulwahn@34051
   883
      and refs_of'_qn: "refs_of' h qn qnrs"
bulwahn@34051
   884
      by (rule refs_of'_Node)
bulwahn@34051
   885
    with 4(12) have r_in: "r \<notin> set xs \<union> set qnrs" by auto
bulwahn@34051
   886
    from qnrs_def 4(12) have "r \<noteq> q" by auto
bulwahn@34051
   887
    with 4(11) 4(12) qnrs_def refs_of'_distinct[OF 4(10)] have q_in: "q \<notin> set xs \<union> set qnrs" by auto
bulwahn@34051
   888
    from 4(11) qnrs_def have no_inter: "set xs \<inter> set qnrs = {}" by auto
haftmann@37725
   889
    from 4(7)[OF 4(9) refs_of'_qn this q_in] 4(4) have q_is_Node: "Ref.get h1 q = Node y qn" by simp
bulwahn@34051
   890
    from 4(7)[OF 4(9) refs_of'_qn no_inter r_in] 4(8) `r \<noteq> q` show ?case
bulwahn@34051
   891
      by simp
bulwahn@34051
   892
  qed
bulwahn@34051
   893
qed
bulwahn@34051
   894
bulwahn@34051
   895
lemma refs_of'_merge:
bulwahn@34051
   896
  assumes "refs_of' h p xs"
bulwahn@34051
   897
  assumes "refs_of' h q ys"
bulwahn@34051
   898
  assumes "crel (merge p q) h h' r"
bulwahn@34051
   899
  assumes "set xs \<inter> set ys = {}"
bulwahn@34051
   900
  assumes "refs_of' h' r rs"
bulwahn@34051
   901
  shows "set rs \<subseteq> set xs \<union> set ys"
bulwahn@34051
   902
proof -
bulwahn@34051
   903
  from assms(1) obtain ps where ps_def: "list_of' h p ps" by (rule refs_of'_list_of')
bulwahn@34051
   904
  from assms(2) obtain qs where qs_def: "list_of' h q qs" by (rule refs_of'_list_of')
bulwahn@34051
   905
  show ?thesis using assms(1) assms(2) assms(4) assms(5)
bulwahn@34051
   906
  proof (induct arbitrary: xs ys rs rule: merge_induct3[OF ps_def qs_def assms(3)])
bulwahn@34051
   907
    case 1
bulwahn@34051
   908
    from 1(5) 1(7) have "rs = ys" by (fastsimp simp add: refs_of'_is_fun)
bulwahn@34051
   909
    thus ?case by auto
bulwahn@34051
   910
  next
bulwahn@34051
   911
    case 2
bulwahn@34051
   912
    from 2(5) 2(8) have "rs = xs" by (auto simp add: refs_of'_is_fun)
bulwahn@34051
   913
    thus ?case by auto
bulwahn@34051
   914
  next
bulwahn@34051
   915
    case (3 x xs' y ys' p q pn qn h1 r1 h' xs ys rs)
bulwahn@34051
   916
    from 3(9) 3(3) obtain pnrs
bulwahn@34051
   917
      where pnrs_def: "xs = p#pnrs"
bulwahn@34051
   918
      and refs_of'_pn: "refs_of' h pn pnrs"
bulwahn@34051
   919
      by (rule refs_of'_Node)
bulwahn@34051
   920
    from 3(10) 3(9) 3(11) pnrs_def refs_of'_distinct[OF 3(9)] have p_in: "p \<notin> set pnrs \<union> set ys" by auto
bulwahn@34051
   921
    from 3(11) pnrs_def have no_inter: "set pnrs \<inter> set ys = {}" by auto
haftmann@37725
   922
    from merge_unchanged[OF refs_of'_pn 3(10) 3(6) no_inter p_in] have p_stays: "Ref.get h1 p = Ref.get h p" ..
bulwahn@34051
   923
    from 3 p_stays obtain r1s
bulwahn@34051
   924
      where rs_def: "rs = p#r1s" and refs_of'_r1:"refs_of' h1 r1 r1s"
bulwahn@34051
   925
      by (auto elim: refs_of'_set_next_ref)
bulwahn@34051
   926
    from 3(7)[OF refs_of'_pn 3(10) no_inter refs_of'_r1] rs_def pnrs_def show ?case by auto
bulwahn@34051
   927
  next
bulwahn@34051
   928
    case (4 x xs' y ys' p q pn qn h1 r1 h' xs ys rs)
bulwahn@34051
   929
    from 4(10) 4(4) obtain qnrs
bulwahn@34051
   930
      where qnrs_def: "ys = q#qnrs"
bulwahn@34051
   931
      and refs_of'_qn: "refs_of' h qn qnrs"
bulwahn@34051
   932
      by (rule refs_of'_Node)
bulwahn@34051
   933
    from 4(10) 4(9) 4(11) qnrs_def refs_of'_distinct[OF 4(10)] have q_in: "q \<notin> set xs \<union> set qnrs" by auto
bulwahn@34051
   934
    from 4(11) qnrs_def have no_inter: "set xs \<inter> set qnrs = {}" by auto
haftmann@37725
   935
    from merge_unchanged[OF 4(9) refs_of'_qn 4(6) no_inter q_in] have q_stays: "Ref.get h1 q = Ref.get h q" ..
bulwahn@34051
   936
    from 4 q_stays obtain r1s
bulwahn@34051
   937
      where rs_def: "rs = q#r1s" and refs_of'_r1:"refs_of' h1 r1 r1s"
bulwahn@34051
   938
      by (auto elim: refs_of'_set_next_ref)
bulwahn@34051
   939
    from 4(7)[OF 4(9) refs_of'_qn no_inter refs_of'_r1] rs_def qnrs_def show ?case by auto
bulwahn@34051
   940
  qed
bulwahn@34051
   941
qed
bulwahn@34051
   942
bulwahn@34051
   943
lemma
bulwahn@34051
   944
  assumes "list_of' h p xs"
bulwahn@34051
   945
  assumes "list_of' h q ys"
bulwahn@34051
   946
  assumes "crel (merge p q) h h' r"
bulwahn@34051
   947
  assumes "\<forall>qrs prs. refs_of' h q qrs \<and> refs_of' h p prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   948
  shows "list_of' h' r (Lmerge xs ys)"
bulwahn@34051
   949
using assms(4)
bulwahn@34051
   950
proof (induct rule: merge_induct3[OF assms(1-3)])
bulwahn@34051
   951
  case 1
bulwahn@34051
   952
  thus ?case by simp
bulwahn@34051
   953
next
bulwahn@34051
   954
  case 2
bulwahn@34051
   955
  thus ?case by simp
bulwahn@34051
   956
next
bulwahn@34051
   957
  case (3 x xs' y ys' p q pn qn h1 r1 h')
bulwahn@34051
   958
  from 3(1) obtain prs where prs_def: "refs_of' h p prs" by (rule list_of'_refs_of')
bulwahn@34051
   959
  from 3(2) obtain qrs where qrs_def: "refs_of' h q qrs" by (rule list_of'_refs_of')
bulwahn@34051
   960
  from prs_def 3(3) obtain pnrs
bulwahn@34051
   961
    where pnrs_def: "prs = p#pnrs"
bulwahn@34051
   962
    and refs_of'_pn: "refs_of' h pn pnrs"
bulwahn@34051
   963
    by (rule refs_of'_Node)
bulwahn@34051
   964
  from prs_def qrs_def 3(9) pnrs_def refs_of'_distinct[OF prs_def] have p_in: "p \<notin> set pnrs \<union> set qrs" by fastsimp
bulwahn@34051
   965
  from prs_def qrs_def 3(9) pnrs_def have no_inter: "set pnrs \<inter> set qrs = {}" by fastsimp
bulwahn@34051
   966
  from no_inter refs_of'_pn qrs_def have no_inter2: "\<forall>qrs prs. refs_of' h q qrs \<and> refs_of' h pn prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   967
    by (fastsimp dest: refs_of'_is_fun)
haftmann@37725
   968
  from merge_unchanged[OF refs_of'_pn qrs_def 3(6) no_inter p_in] have p_stays: "Ref.get h1 p = Ref.get h p" ..
bulwahn@34051
   969
  from 3(7)[OF no_inter2] obtain rs where rs_def: "refs_of' h1 r1 rs" by (rule list_of'_refs_of')
bulwahn@34051
   970
  from refs_of'_merge[OF refs_of'_pn qrs_def 3(6) no_inter this] p_in have p_rs: "p \<notin> set rs" by auto
bulwahn@34051
   971
  with 3(7)[OF no_inter2] 3(1-5) 3(8) p_rs rs_def p_stays
bulwahn@34051
   972
  show ?case by auto
bulwahn@34051
   973
next
bulwahn@34051
   974
  case (4 x xs' y ys' p q pn qn h1 r1 h')
bulwahn@34051
   975
  from 4(1) obtain prs where prs_def: "refs_of' h p prs" by (rule list_of'_refs_of')
bulwahn@34051
   976
  from 4(2) obtain qrs where qrs_def: "refs_of' h q qrs" by (rule list_of'_refs_of')
bulwahn@34051
   977
  from qrs_def 4(4) obtain qnrs
bulwahn@34051
   978
    where qnrs_def: "qrs = q#qnrs"
bulwahn@34051
   979
    and refs_of'_qn: "refs_of' h qn qnrs"
bulwahn@34051
   980
    by (rule refs_of'_Node)
bulwahn@34051
   981
  from prs_def qrs_def 4(9) qnrs_def refs_of'_distinct[OF qrs_def] have q_in: "q \<notin> set prs \<union> set qnrs" by fastsimp
bulwahn@34051
   982
  from prs_def qrs_def 4(9) qnrs_def have no_inter: "set prs \<inter> set qnrs = {}" by fastsimp
bulwahn@34051
   983
  from no_inter refs_of'_qn prs_def have no_inter2: "\<forall>qrs prs. refs_of' h qn qrs \<and> refs_of' h p prs \<longrightarrow> set prs \<inter> set qrs = {}"
bulwahn@34051
   984
    by (fastsimp dest: refs_of'_is_fun)
haftmann@37725
   985
  from merge_unchanged[OF prs_def refs_of'_qn 4(6) no_inter q_in] have q_stays: "Ref.get h1 q = Ref.get h q" ..
bulwahn@34051
   986
  from 4(7)[OF no_inter2] obtain rs where rs_def: "refs_of' h1 r1 rs" by (rule list_of'_refs_of')
bulwahn@34051
   987
  from refs_of'_merge[OF prs_def refs_of'_qn 4(6) no_inter this] q_in have q_rs: "q \<notin> set rs" by auto
bulwahn@34051
   988
  with 4(7)[OF no_inter2] 4(1-5) 4(8) q_rs rs_def q_stays
bulwahn@34051
   989
  show ?case by auto
bulwahn@34051
   990
qed
bulwahn@34051
   991
bulwahn@34051
   992
section {* Code generation *}
bulwahn@34051
   993
bulwahn@34051
   994
text {* A simple example program *}
bulwahn@34051
   995
krauss@37792
   996
definition test_1 where "test_1 = (do { ll_xs <- make_llist [1..(15::int)]; xs <- traverse ll_xs; return xs })" 
krauss@37792
   997
definition test_2 where "test_2 = (do { ll_xs <- make_llist [1..(15::int)]; ll_ys <- rev ll_xs; ys <- traverse ll_ys; return ys })"
bulwahn@34051
   998
bulwahn@34051
   999
definition test_3 where "test_3 =
krauss@37792
  1000
  (do {
bulwahn@34051
  1001
    ll_xs \<leftarrow> make_llist (filter (%n. n mod 2 = 0) [2..8]);
bulwahn@34051
  1002
    ll_ys \<leftarrow> make_llist (filter (%n. n mod 2 = 1) [5..11]);
haftmann@37725
  1003
    r \<leftarrow> ref ll_xs;
haftmann@37725
  1004
    q \<leftarrow> ref ll_ys;
bulwahn@34051
  1005
    p \<leftarrow> merge r q;
bulwahn@34051
  1006
    ll_zs \<leftarrow> !p;
bulwahn@34051
  1007
    zs \<leftarrow> traverse ll_zs;
bulwahn@34051
  1008
    return zs
krauss@37792
  1009
  })"
bulwahn@34051
  1010
haftmann@35041
  1011
code_reserved SML upto
haftmann@35041
  1012
bulwahn@34051
  1013
ML {* @{code test_1} () *}
bulwahn@34051
  1014
ML {* @{code test_2} () *}
bulwahn@34051
  1015
ML {* @{code test_3} () *}
bulwahn@34051
  1016
haftmann@37879
  1017
export_code test_1 test_2 test_3 checking SML SML_imp OCaml? OCaml_imp? Haskell? Scala?
haftmann@37750
  1018
haftmann@37725
  1019
end