File: resizable_array.mlw

package info (click to toggle)
why3 1.8.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,028 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (162 lines) | stat: -rw-r--r-- 4,596 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

module ResizableArraySpec

  use int.Int
  use map.Map
  use map.Const

  type rarray 'a = private {
    ghost mutable length: int;
    ghost mutable data: map int 'a
  }

  function ([]) (r: rarray 'a) (i: int) : 'a = Map.get r.data i
  val function ([<-]) (r: rarray 'a) (i: int) (v: 'a) : rarray 'a
    ensures { result.length = r.length }
    ensures { result.data = Map.set r.data i v }

  val make (len: int) (dummy: 'a) : rarray 'a
    requires { 0 <= len }
    ensures  { result.length = len }
    ensures  { result.data = Const.const dummy }
    (* ensures  { forall i: int. 0 <= i < len -> result[i] = dummy } *)

  val ([]) (r: rarray 'a) (i: int) : 'a
    requires { 0 <= i < r.length } ensures { result = r[i] }

  val ([]<-) (r: rarray 'a) (i: int) (v: 'a) : unit writes {r}
    requires { 0 <= i < r.length } ensures { r = (old r)[i <- v] }

  val resize (r: rarray 'a) (len: int) : unit writes {r}
    requires { 0 <= len }
    ensures  { r.length = len }
    ensures  { forall i: int.
               0 <= i < old r.length -> i < len -> r[i] = (old r)[i] }

  val append (r1: rarray 'a) (r2: rarray 'a) : unit writes {r1}
    ensures { r1.length = (old r1.length) + r2.length }
    ensures { forall i: int. 0 <= i < r1.length ->
               (i < old r1.length  -> r1[i] = (old r1)[i]) /\
               (old r1.length <= i -> r1[i] = r2[i - old r1.length]) }

end

module ResizableArrayImplem (* : ResizableArraySpec *)

  use int.Int
  use int.MinMax
  use array.Array as A

  type rarray 'a =
    { dummy: 'a; mutable length: int; mutable data: A.array 'a }
    invariant { 0 <= length <= A.length data }
    invariant { forall i: int. length <= i < A.length data ->
                  A.([]) data i = dummy }
    by { dummy = any 'a; length = 0; data = A.make 0 (any 'a) }

  function ([]) (r: rarray 'a) (i: int) : 'a = A.([]) r.data i

(*
function make (len: int) (dummy: 'a) : rarray 'a =
    { dummy = dummy; length = len; data = A.make len dummy }
*)

  let make (len: int) (dummy: 'a) : rarray 'a
    requires { 0 <= len }
    ensures { result.dummy = dummy }
    ensures { result.length = len }
    ensures { forall i:int. 0 <= i < len -> A.([]) result.data i = dummy }
    =
    { dummy = dummy; length = len; data = A.make len dummy }

  let ([]) (r: rarray 'a) (i: int) : 'a
    requires { 0 <= i < r.length }
    =
    A.([]) r.data i

  let ([]<-) (r: rarray 'a) (i: int) (v: 'a) : unit
    requires { 0 <= i < r.length }
    ensures { r.data.A.elts = A.Map.([<-]) (old r).data.A.elts i v }
    =
    A.([]<-) r.data i v

  let resize (r: rarray 'a) (len: int) : unit
    requires { 0 <= len }
    ensures  { r.length = len }
    ensures  { forall i: int.
                 0 <= i < old r.length -> i < len -> r[i] = (old r)[i] }
    =
    let n = A.length r.data in
    if len > n then begin
      let a = A.make (max len (2 * n)) r.dummy in
      A.blit r.data 0 a 0 n;
      r.data <- a
    end else begin
      A.fill r.data len (n - len) r.dummy
    end;
    r.length <- len

  let append (r1: rarray 'a) (r2: rarray 'a) : unit
    ensures { r1.length = old r1.length + r2.length }
    ensures { forall i: int. 0 <= i < r1.length ->
               (i < old r1.length  -> r1[i] = (old r1)[i]) /\
               (old r1.length <= i -> r1[i] = r2[i - old r1.length]) }
    =
    let n1 = length r1 in
    resize r1 (length r1 + length r2);
    A.blit r2.data 0 r1.data n1 (length r2)

  (* sanity checks for WhyML typing system *)

(*
  let test_reset1 (r: rarray) =
    let a = A.make 10 dummy in
    r.data <- a;
    A.([]) a 0 (* <-- we cannot access array a anymore *)

  let test_reset2 (r: rarray) =
     let b = r.data in
     r.data <- A.make 10 dummy;
     let x = A.([]) r.data 0 in (* <-- this is accepted *)
     let y = A.([]) b      0 in (* <-- but we cannot access array b anymore *)
     ()

  (* the same, using resize *)
  let test_reset3 (r: rarray) =
     let c = r.data in
     resize r 10;
     let x = A.([]) r.data 0 in (* <-- this is accepted *)
     let y = A.([]) c      0 in (* <-- but we cannot access array c anymore *)
     ()
*)

end

module Test

  use int.Int
  use ResizableArrayImplem

  let test1 () =
    let r = make 10 0 in
    assert { r.length = 10 };
    r[0] <- 17;
    resize r 7;
    assert { r[0] = 17 };
    assert { r.length = 7 }

  let test2 () =
    let r1 = make 10 0 in
    r1[0] <- 17;
    let r2 = make 10 0 in
    r2[0] <- 42;
    append r1 r2;
    assert { r1.length = 20 };
    assert { r1[0] = 17 };
    let x = r1[10] in
    assert { x = 42 };
    let y = r2[0] in
    assert { y = 42 };
    ()

end