6 use int.EuclideanDivision as E
8 type list 'a = private {
11 } invariant { len = length elts }
13 meta coercion function elts
15 function ([]) (l: list 'a) (i: int) : 'a
17 if i >= 0 then Seq.(l[i]) else Seq.(l[l.len + i])
19 val ghost function create (s: seq 'a) : list 'a
20 ensures { result = s }
21 ensures { len result = length s }
23 function ([<-]) (l: list 'a) (i: int) (v: 'a) : list 'a
25 create (if i >= 0 then Seq.(l.elts[i <- v]) else Seq.(l.elts[l.len + i <- v]))
27 let ([]) (l: list 'a) (i: int) : 'a
28 requires { [@expl:index in array bounds] -len l <= i < len l }
29 ensures { result = l[i] }
30 = if i >= 0 then Seq.(l.elts[i]) else Seq.(l.elts[len l + i])
32 val ([]<-) (l: list 'a) (i: int) (v: 'a) : unit
33 requires { [@expl:index in array bounds] -len l <= i < len l }
35 ensures { l.elts = (old l)[i <- v].elts }
37 val empty () : list 'a
38 ensures { result = Seq.empty }
40 val make (n: int) (v: 'a) : list 'a
42 ensures { len result = n }
43 ensures { forall i. -n <= i < n -> result[i] = v }
46 (* ad-hoc facts about exchange *)
50 function occurrence (v: 'a) (l: list 'a) (lo hi: int): int =
55 (* Python's division and modulus according are neither Euclidean division,
56 nor computer division, but something else defined in
57 https://docs.python.org/3/reference/expressions.html *)
59 function (//) (x y: int) : int =
61 if y >= 0 then q else if E.mod x y > 0 then q-1 else q
62 function (%) (x y: int) : int =
64 if y >= 0 then r else if r > 0 then r+y else r
67 forall x y:int. y <> 0 -> x = y * (x // y) + (x % y)
69 forall x y:int. y <> 0 -> 0 <= abs (x % y) < abs y
71 forall x y:int. y <> 0 -> if y < 0 then x % y <= 0 else x % y >= 0
73 val (//) (x y: int) : int
74 requires { [@expl:check division by zero] y <> 0 }
75 ensures { result = x // y }
77 val (%) (x y: int) : int
78 requires { [@expl:check division by zero] y <> 0 }
79 ensures { result = x % y }
82 val randint (l u: int) : int
83 requires { [@expl:valid range] l <= u }
84 ensures { l <= result <= u }
88 function pow (x y: int) : int = power x y
92 val int (n: int) : int
93 ensures { result = n }
97 val range (lo hi: int) : list int
98 requires { [@expl:valid range] lo <= hi }
99 ensures { len result = hi - lo }
100 ensures { forall i. 0 <= i < hi - lo -> result[i] = i + lo }
102 let range3 (le ri step: int) : list int
103 requires { [@expl:valid range] (le <= ri /\ step > 0) \/ (ri <= le /\ step < 0) }
104 ensures { len result = E.div (ri - le) step + if E.mod (ri - le) step <> 0 then 1 else 0 }
105 ensures { forall i. 0 <= i < len result -> result[i] = le + i * step }
106 = let n = E.div (ri - le) step + if E.mod (ri - le) step <> 0 then 1 else 0 in
109 invariant { forall j. 0 <= j < i -> a[j] = le + j * step }
110 a[i] <- le + i * step;
112 assert { step > 0 -> le + n * step >= ri
113 /\ step > 0 -> le + (n-1) * step < ri
114 /\ step < 0 -> le + n * step <= ri
115 /\ step < 0 -> le + (n-1) * step > ri };
118 val pop (l: list 'a) : 'a
119 requires { len l > 0 }
121 ensures { len l = len (old l) - 1 }
122 ensures { result = (old l)[len l] }
123 ensures { forall i. 0 <= i < len l -> l[i] = (old l)[i] }
125 val append (l: list 'a) (v: 'a) : unit
127 ensures { len l = len (old l) + 1 }
128 ensures { l[len (old l)] = v }
129 ensures { forall i. 0 <= i < len (old l) -> l[i] = (old l)[i] }
131 val function add_list (a1: list 'a) (a2: list 'a) : list 'a
132 ensures { len result = len a1 + len a2 }
133 ensures { forall i. 0 <= i < len a1 -> result[i] = a1[i] }
134 ensures { forall i. len a1 <= i < len result -> result[i] = a2[i-len a1] }
136 function transform_idx (l: list 'a) (i: int): int
138 if i < 0 then len l + i else i
140 val function slice (l: list 'a) (lo hi: int) : list 'a
141 requires { transform_idx l lo >= 0 }
142 requires { transform_idx l hi <= len l }
143 requires { transform_idx l lo <= transform_idx l hi }
144 ensures { len result = transform_idx l hi - transform_idx l lo }
145 ensures { forall i. 0 <= i < len result -> result[i] = l[transform_idx l lo + i] }
147 val clear (l : list 'a) : unit
149 ensures { len l = 0 }
151 val copy (l: list 'a): list 'a
152 ensures { len result = len l }
153 ensures { result.elts = l.elts }
157 predicate is_permutation (l1 l2: list 'a)
158 = ([@expl:equality of length] length l1 = length l2)
159 /\ ([@expl:equality of elements] permut l1 l2 0 (length l2))
161 val sort (l : list int) : unit
163 ensures { is_permutation l (old l) }
164 ensures { forall i, j. 0 <= i <= j < len(l) -> l[i] <= l[j] }
166 val reverse (l: list 'a) : unit
168 ensures { len l = len (old l) }
169 ensures { forall i. 0 <= i < len l -> l[i] = (old l)[-(i+1)] }
170 ensures { forall i. 0 <= i < len l -> (old l)[i] = l[-(i+1)] }
171 ensures { is_permutation l (old l) }