src/HOL/Hoare/Heap.thy
author wenzelm
Mon, 11 Sep 2006 21:35:19 +0200
changeset 20503 503ac4c5ef91
parent 19399 fd2ba98056a2
child 35416 d8d7d1b785af
permissions -rw-r--r--
induct method: renamed 'fixing' to 'arbitrary';
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13875
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     1
(*  Title:      HOL/Hoare/Heap.thy
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     2
    ID:         $Id$
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     3
    Author:     Tobias Nipkow
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     4
    Copyright   2002 TUM
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     5
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     6
Pointers, heaps and heap abstractions.
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     7
See the paper by Mehta and Nipkow.
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     8
*)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
     9
16417
9bc16273c2d4 migrated theory headers to new format
haftmann
parents: 13875
diff changeset
    10
theory Heap imports Main begin
13875
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    11
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    12
subsection "References"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    13
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    14
datatype 'a ref = Null | Ref 'a
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    15
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    16
lemma not_Null_eq [iff]: "(x ~= Null) = (EX y. x = Ref y)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    17
  by (induct x) auto
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    18
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    19
lemma not_Ref_eq [iff]: "(ALL y. x ~= Ref y) = (x = Null)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    20
  by (induct x) auto
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    21
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    22
consts addr :: "'a ref \<Rightarrow> 'a"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    23
primrec "addr(Ref a) = a"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    24
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    25
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    26
section "The heap"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    27
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    28
subsection "Paths in the heap"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    29
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    30
consts
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    31
 Path :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list \<Rightarrow> 'a ref \<Rightarrow> bool"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    32
primrec
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    33
"Path h x [] y = (x = y)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    34
"Path h x (a#as) y = (x = Ref a \<and> Path h (h a) as y)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    35
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    36
lemma [iff]: "Path h Null xs y = (xs = [] \<and> y = Null)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    37
apply(case_tac xs)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    38
apply fastsimp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    39
apply fastsimp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    40
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    41
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    42
lemma [simp]: "Path h (Ref a) as z =
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    43
 (as = [] \<and> z = Ref a  \<or>  (\<exists>bs. as = a#bs \<and> Path h (h a) bs z))"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    44
apply(case_tac as)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    45
apply fastsimp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    46
apply fastsimp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    47
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    48
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    49
lemma [simp]: "\<And>x. Path f x (as@bs) z = (\<exists>y. Path f x as y \<and> Path f y bs z)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    50
by(induct as, simp+)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    51
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    52
lemma Path_upd[simp]:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    53
 "\<And>x. u \<notin> set as \<Longrightarrow> Path (f(u := v)) x as y = Path f x as y"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    54
by(induct as, simp, simp add:eq_sym_conv)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    55
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    56
lemma Path_snoc:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    57
 "Path (f(a := q)) p as (Ref a) \<Longrightarrow> Path (f(a := q)) p (as @ [a]) q"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    58
by simp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    59
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    60
19399
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    61
subsection "Non-repeating paths"
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    62
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    63
constdefs
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    64
  distPath :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list \<Rightarrow> 'a ref \<Rightarrow> bool"
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    65
  "distPath h x as y   \<equiv>   Path h x as y  \<and>  distinct as"
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    66
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    67
text{* The term @{term"distPath h x as y"} expresses the fact that a
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    68
non-repeating path @{term as} connects location @{term x} to location
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    69
@{term y} by means of the @{term h} field. In the case where @{text "x
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    70
= y"}, and there is a cycle from @{term x} to itself, @{term as} can
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    71
be both @{term "[]"} and the non-repeating list of nodes in the
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    72
cycle. *}
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    73
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    74
lemma neq_dP: "p \<noteq> q \<Longrightarrow> Path h p Ps q \<Longrightarrow> distinct Ps \<Longrightarrow>
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    75
 EX a Qs. p = Ref a & Ps = a#Qs & a \<notin> set Qs"
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    76
by (case_tac Ps, auto)
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    77
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    78
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    79
lemma neq_dP_disp: "\<lbrakk> p \<noteq> q; distPath h p Ps q \<rbrakk> \<Longrightarrow>
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    80
 EX a Qs. p = Ref a \<and> Ps = a#Qs \<and> a \<notin> set Qs"
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    81
apply (simp only:distPath_def)
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    82
by (case_tac Ps, auto)
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    83
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
    84
13875
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    85
subsection "Lists on the heap"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    86
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    87
subsubsection "Relational abstraction"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    88
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    89
constdefs
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    90
 List :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list \<Rightarrow> bool"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    91
"List h x as == Path h x as Null"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    92
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    93
lemma [simp]: "List h x [] = (x = Null)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    94
by(simp add:List_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    95
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    96
lemma [simp]: "List h x (a#as) = (x = Ref a \<and> List h (h a) as)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    97
by(simp add:List_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    98
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
    99
lemma [simp]: "List h Null as = (as = [])"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   100
by(case_tac as, simp_all)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   101
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   102
lemma List_Ref[simp]: "List h (Ref a) as = (\<exists>bs. as = a#bs \<and> List h (h a) bs)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   103
by(case_tac as, simp_all, fast)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   104
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   105
theorem notin_List_update[simp]:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   106
 "\<And>x. a \<notin> set as \<Longrightarrow> List (h(a := y)) x as = List h x as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   107
apply(induct as)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   108
apply simp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   109
apply(clarsimp simp add:fun_upd_apply)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   110
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   111
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   112
lemma List_unique: "\<And>x bs. List h x as \<Longrightarrow> List h x bs \<Longrightarrow> as = bs"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   113
by(induct as, simp, clarsimp)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   114
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   115
lemma List_unique1: "List h p as \<Longrightarrow> \<exists>!as. List h p as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   116
by(blast intro:List_unique)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   117
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   118
lemma List_app: "\<And>x. List h x (as@bs) = (\<exists>y. Path h x as y \<and> List h y bs)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   119
by(induct as, simp, clarsimp)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   120
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   121
lemma List_hd_not_in_tl[simp]: "List h (h a) as \<Longrightarrow> a \<notin> set as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   122
apply (clarsimp simp add:in_set_conv_decomp)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   123
apply(frule List_app[THEN iffD1])
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   124
apply(fastsimp dest: List_unique)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   125
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   126
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   127
lemma List_distinct[simp]: "\<And>x. List h x as \<Longrightarrow> distinct as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   128
apply(induct as, simp)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   129
apply(fastsimp dest:List_hd_not_in_tl)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   130
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   131
19399
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   132
lemma Path_is_List:
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   133
  "\<lbrakk>Path h b Ps (Ref a); a \<notin> set Ps\<rbrakk> \<Longrightarrow> List (h(a := Null)) b (Ps @ [a])"
20503
503ac4c5ef91 induct method: renamed 'fixing' to 'arbitrary';
wenzelm
parents: 19399
diff changeset
   134
apply (induct Ps arbitrary: b)
19399
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   135
apply (auto simp add:fun_upd_apply)
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   136
done
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   137
fd2ba98056a2 Included cyclic list examples
nipkow
parents: 16417
diff changeset
   138
13875
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   139
subsection "Functional abstraction"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   140
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   141
constdefs
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   142
 islist :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> bool"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   143
"islist h p == \<exists>as. List h p as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   144
 list :: "('a \<Rightarrow> 'a ref) \<Rightarrow> 'a ref \<Rightarrow> 'a list"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   145
"list h p == SOME as. List h p as"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   146
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   147
lemma List_conv_islist_list: "List h p as = (islist h p \<and> as = list h p)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   148
apply(simp add:islist_def list_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   149
apply(rule iffI)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   150
apply(rule conjI)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   151
apply blast
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   152
apply(subst some1_equality)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   153
  apply(erule List_unique1)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   154
 apply assumption
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   155
apply(rule refl)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   156
apply simp
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   157
apply(rule someI_ex)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   158
apply fast
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   159
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   160
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   161
lemma [simp]: "islist h Null"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   162
by(simp add:islist_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   163
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   164
lemma [simp]: "islist h (Ref a) = islist h (h a)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   165
by(simp add:islist_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   166
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   167
lemma [simp]: "list h Null = []"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   168
by(simp add:list_def)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   169
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   170
lemma list_Ref_conv[simp]:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   171
 "islist h (h a) \<Longrightarrow> list h (Ref a) = a # list h (h a)"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   172
apply(insert List_Ref[of h])
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   173
apply(fastsimp simp:List_conv_islist_list)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   174
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   175
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   176
lemma [simp]: "islist h (h a) \<Longrightarrow> a \<notin> set(list h (h a))"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   177
apply(insert List_hd_not_in_tl[of h])
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   178
apply(simp add:List_conv_islist_list)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   179
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   180
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   181
lemma list_upd_conv[simp]:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   182
 "islist h p \<Longrightarrow> y \<notin> set(list h p) \<Longrightarrow> list (h(y := q)) p = list h p"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   183
apply(drule notin_List_update[of _ _ h q p])
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   184
apply(simp add:List_conv_islist_list)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   185
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   186
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   187
lemma islist_upd[simp]:
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   188
 "islist h p \<Longrightarrow> y \<notin> set(list h p) \<Longrightarrow> islist (h(y := q)) p"
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   189
apply(frule notin_List_update[of _ _ h q p])
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   190
apply(simp add:List_conv_islist_list)
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   191
done
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   192
12997e3ddd8d *** empty log message ***
nipkow
parents:
diff changeset
   193
end