2012-09-28 20:43:29 +02:00
|
|
|
|
2014-01-27 14:14:28 +01:00
|
|
|
module ResizableArraySpec
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use map.Map
|
|
|
|
|
use map.Const
|
2014-01-27 14:14:28 +01:00
|
|
|
|
2016-03-23 17:20:20 +01:00
|
|
|
type rarray 'a = private {
|
|
|
|
|
ghost mutable length: int;
|
|
|
|
|
ghost mutable data: map int 'a
|
|
|
|
|
}
|
2014-01-27 14:14:28 +01:00
|
|
|
|
|
|
|
|
function ([]) (r: rarray 'a) (i: int) : 'a = Map.get r.data i
|
2016-03-23 17:20:20 +01:00
|
|
|
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 }
|
2014-01-27 14:14:28 +01:00
|
|
|
|
|
|
|
|
val make (len: int) (dummy: 'a) : rarray 'a
|
|
|
|
|
requires { 0 <= len }
|
|
|
|
|
ensures { result.length = len }
|
2015-07-06 14:02:05 +02:00
|
|
|
ensures { result.data = Const.const dummy }
|
2014-01-27 14:14:28 +01:00
|
|
|
(* 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] }
|
|
|
|
|
|
2021-03-12 20:56:41 +01:00
|
|
|
val ([]<-) (r: rarray 'a) (i: int) (v: 'a) : unit writes {r}
|
2014-01-27 14:14:28 +01:00
|
|
|
requires { 0 <= i < r.length } ensures { r = (old r)[i <- v] }
|
|
|
|
|
|
2021-03-12 20:56:41 +01:00
|
|
|
val resize (r: rarray 'a) (len: int) : unit writes {r}
|
2014-01-27 14:14:28 +01:00
|
|
|
requires { 0 <= len }
|
|
|
|
|
ensures { r.length = len }
|
|
|
|
|
ensures { forall i: int.
|
|
|
|
|
0 <= i < old r.length -> i < len -> r[i] = (old r)[i] }
|
|
|
|
|
|
2021-03-12 20:56:41 +01:00
|
|
|
val append (r1: rarray 'a) (r2: rarray 'a) : unit writes {r1}
|
|
|
|
|
ensures { r1.length = (old r1.length) + r2.length }
|
2014-01-27 14:14:28 +01:00
|
|
|
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 *)
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use int.MinMax
|
2012-10-02 17:05:06 +02:00
|
|
|
use array.Array as A
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
type rarray 'a =
|
|
|
|
|
{ dummy: 'a; mutable length: int; mutable data: A.array 'a }
|
2016-03-23 17:20:20 +01:00
|
|
|
invariant { 0 <= length <= A.length data }
|
|
|
|
|
invariant { forall i: int. length <= i < A.length data ->
|
|
|
|
|
A.([]) data i = dummy }
|
2017-06-26 00:01:12 +02:00
|
|
|
by { dummy = any 'a; length = 0; data = A.make 0 (any 'a) }
|
2012-10-02 17:05:06 +02:00
|
|
|
|
2016-03-23 17:20:20 +01:00
|
|
|
function ([]) (r: rarray 'a) (i: int) : 'a = A.([]) r.data i
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2015-07-06 14:02:05 +02:00
|
|
|
(*
|
|
|
|
|
function make (len: int) (dummy: 'a) : rarray 'a =
|
2013-03-04 13:04:37 +01:00
|
|
|
{ dummy = dummy; length = len; data = A.make len dummy }
|
2015-07-06 14:02:05 +02:00
|
|
|
*)
|
2012-10-02 17:56:08 +02:00
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
let make (len: int) (dummy: 'a) : rarray 'a
|
2015-07-06 14:02:05 +02:00
|
|
|
requires { 0 <= len }
|
|
|
|
|
ensures { result.dummy = dummy }
|
|
|
|
|
ensures { result.length = len }
|
2016-03-23 17:20:20 +01:00
|
|
|
ensures { forall i:int. 0 <= i < len -> A.([]) result.data i = dummy }
|
2013-03-04 13:04:37 +01:00
|
|
|
=
|
|
|
|
|
{ dummy = dummy; length = len; data = A.make len dummy }
|
2012-10-02 17:56:08 +02:00
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
let ([]) (r: rarray 'a) (i: int) : 'a
|
2016-03-23 17:20:20 +01:00
|
|
|
requires { 0 <= i < r.length }
|
2013-03-04 13:04:37 +01:00
|
|
|
=
|
|
|
|
|
A.([]) r.data i
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
let ([]<-) (r: rarray 'a) (i: int) (v: 'a) : unit
|
2016-03-23 17:20:20 +01:00
|
|
|
requires { 0 <= i < r.length }
|
2018-07-02 17:10:35 +02:00
|
|
|
ensures { r.data.A.elts = A.Map.([<-]) (old r).data.A.elts i v }
|
2013-03-04 13:04:37 +01:00
|
|
|
=
|
|
|
|
|
A.([]<-) r.data i v
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
let resize (r: rarray 'a) (len: int) : unit
|
2012-10-13 00:23:29 +02:00
|
|
|
requires { 0 <= len }
|
2013-03-04 13:04:37 +01:00
|
|
|
ensures { r.length = len }
|
|
|
|
|
ensures { forall i: int.
|
2014-01-27 14:14:28 +01:00
|
|
|
0 <= i < old r.length -> i < len -> r[i] = (old r)[i] }
|
2013-03-04 13:04:37 +01:00
|
|
|
=
|
|
|
|
|
let n = A.length r.data in
|
2012-09-28 20:43:29 +02:00
|
|
|
if len > n then begin
|
2013-03-04 13:04:37 +01:00
|
|
|
let a = A.make (max len (2 * n)) r.dummy in
|
2012-10-02 17:05:06 +02:00
|
|
|
A.blit r.data 0 a 0 n;
|
2012-09-28 20:43:29 +02:00
|
|
|
r.data <- a
|
2013-03-04 13:04:37 +01:00
|
|
|
end else begin
|
|
|
|
|
A.fill r.data len (n - len) r.dummy
|
2012-09-28 20:43:29 +02:00
|
|
|
end;
|
|
|
|
|
r.length <- len
|
|
|
|
|
|
2013-03-04 13:04:37 +01:00
|
|
|
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
|
2012-10-13 00:23:29 +02:00
|
|
|
resize r1 (length r1 + length r2);
|
|
|
|
|
A.blit r2.data 0 r1.data n1 (length r2)
|
2012-09-28 20:43:29 +02:00
|
|
|
|
2012-10-02 17:56:08 +02:00
|
|
|
(* 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
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use ResizableArrayImplem
|
2012-10-02 17:56:08 +02:00
|
|
|
|
|
|
|
|
let test1 () =
|
2013-03-04 13:04:37 +01:00
|
|
|
let r = make 10 0 in
|
2012-10-02 17:56:08 +02:00
|
|
|
assert { r.length = 10 };
|
|
|
|
|
r[0] <- 17;
|
|
|
|
|
resize r 7;
|
|
|
|
|
assert { r[0] = 17 };
|
|
|
|
|
assert { r.length = 7 }
|
|
|
|
|
|
|
|
|
|
let test2 () =
|
2013-03-04 13:04:37 +01:00
|
|
|
let r1 = make 10 0 in
|
2012-10-02 17:56:08 +02:00
|
|
|
r1[0] <- 17;
|
2013-03-04 13:04:37 +01:00
|
|
|
let r2 = make 10 0 in
|
2012-10-02 17:56:08 +02:00
|
|
|
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 };
|
|
|
|
|
()
|
|
|
|
|
|
2012-09-28 20:43:29 +02:00
|
|
|
end
|