File: reverse.why

package info (click to toggle)
why 2.30%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 26,916 kB
  • sloc: ml: 116,979; java: 9,376; ansic: 5,175; makefile: 1,335; sh: 531; lisp: 127
file content (141 lines) | stat: -rw-r--r-- 3,468 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

(* in-place list reversal revisited with algebraic types *)


(* logical polymorphic lists *)

type 'a list = Nil | Cons('a, 'a list)

goal discr_test:
     forall x:'a. forall l:'a list. not(Nil = Cons(x,l))

(* append function *)
logic app : 'a list, 'a list -> 'a list

axiom app_def: forall l1,l2:'a list [app(l1,l2)].
  app(l1,l2) = match l1 with
    | Nil -> l2
    | Cons(x,l) -> Cons(x,app(l,l2))
  end

goal app_test0: 
     app(Nil,Nil) = Nil

goal app_test1: 
     app(Cons(1,Nil),Nil) = Cons(1,Nil)

goal app_test2: 
     app(Nil,Cons(1,Nil)) = Cons(1,Nil)

goal app_test3: 
     app(Cons(1,Nil),Cons(2,Nil)) = Cons(1,Cons(2,Nil))

(* rev2(l1,l2) produces rev(l1)@l2 *)
logic rev2 : 'a list, 'a list -> 'a list

axiom rev2_def: forall l1,l2:'a list [rev2(l1,l2)].
  rev2(l1,l2) = match l1 with 
     | Nil -> l2
     | Cons(x,l) -> rev2(l,Cons(x,l2))
  end

goal rev2_test: 
     forall l:'a list. rev2(Nil,l) = l

function rev(l:'a list):'a list = rev2(l,Nil)

goal rev_test0: 
     rev(Nil) = Nil

goal rev_test1: 
     rev(Cons(1,Nil)) = Cons(1,Nil)

goal rev_test2: 
     rev(Cons(1,Cons(2,Nil))) = Cons(2,Cons(1,Nil))

goal rev_test3: 
     rev(Cons(1,Cons(2,(Cons(3,Nil))))) = Cons(3,Cons(2,Cons(1,Nil)))

(* disjoint predicate *)
logic disjoint : 'a list, 'a list -> prop

axiom disjoint_nil_l: forall l:'a list. disjoint(Nil,l)
axiom disjoint_l_nil: forall l:'a list. disjoint(l,Nil)

(* modelisation of pointers *)

type pointer

logic null : pointer

parameter eq_pointer : 
  p1:pointer -> p2:pointer -> {} bool { if result then p1=p2 else p1<>p2 }

parameter ne_pointer : 
  p1:pointer -> p2:pointer -> {} bool { if result then p1<>p2 else p1=p2 }

parameter is_null : p:pointer -> {} bool { if result then p=null else p<>null }



(* modelisation of the memory heap *)

type pointer_store

logic pget : pointer_store, pointer -> pointer
logic pset : pointer_store, pointer, pointer -> pointer_store

logic is_valid_pointer : pointer -> prop

axiom null_not_valid: not is_valid_pointer(null)

parameter Ltl : pointer_store ref


(* null-terminated program lists *)
 
(*
inductive lpath : pointer_store, pointer, pointer list, pointer -> prop =
| lpath_nil: lpath(tl, p, Nil, p)
| lpath_cons: is_valid_pointer(tl,p) and lpath(tl, pget(tl,p), l, q) 
      -> lpath(tl, p, Cons(p,l), q)
*)

(* llist(tl,p,l) is true whenever p is a null-terminated list of pointers,
   and l is the list of pointers met on the path from p to null *)
inductive llist : pointer_store, pointer, pointer list -> prop =
| llist_nil: forall tl:pointer_store. llist(tl, null, Nil)
| llist_cons: forall tl:pointer_store. forall p:pointer. 
  forall l:pointer list. 
  is_valid_pointer(p) and llist(tl, pget(tl,p), l) 
      -> llist(tl, p, Cons(p,l))

goal null_model_is_Nil: 
     forall tl:pointer_store. forall l:pointer list. 
           llist(tl, null, l) -> l = Nil

(* in-place list reversal *)

let reverse (p0:pointer) (p0_model:pointer list) =
  { llist(Ltl, p0, p0_model) }
  init:
  let p = ref p0 in
  let r = ref !p in
  begin
    p := null;
    while (ne_pointer !r null) do
      { invariant exists lp:pointer list. exists lr:pointer list.
                  llist(Ltl, p, lp) and llist(Ltl, r, lr) 
		  and disjoint(lp, lr) and 
	           rev2(lr, lp) = rev(p0_model) }
      let q = ref !r in
      begin
      r := (pget !Ltl !r);
      Ltl := (pset !Ltl !q !p);
      p := !q
      end
    done;
    !p
  end
  { llist(Ltl, result, rev(p0_model)) }