summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSon Ho2022-02-13 20:25:40 +0100
committerSon Ho2022-02-13 20:25:40 +0100
commita2b032dbcfa1d001e6c908d7bf0e605515f41e0c (patch)
treee2ade9bbe46dc9ea96b53ca3492ef8a081662269
parent56fadb49bc5d253f39fb44e97dd841a38c70c548 (diff)
Do more cleaning
-rw-r--r--tests/hashmap/Hashmap.Properties.fst288
1 files changed, 141 insertions, 147 deletions
diff --git a/tests/hashmap/Hashmap.Properties.fst b/tests/hashmap/Hashmap.Properties.fst
index d280d537..a6becc96 100644
--- a/tests/hashmap/Hashmap.Properties.fst
+++ b/tests/hashmap/Hashmap.Properties.fst
@@ -445,6 +445,7 @@ let slot_t_v #t = list_t_v #t
let slots_t_v (#t : Type0) (slots : slots_t t) : slots_s t =
map slot_t_v slots
+/// Representation function for the slots, seen as an associative list.
let slots_t_al_v (#t : Type0) (slots : slots_t t) : assoc_list t =
flatten (map list_t_v slots)
@@ -452,21 +453,18 @@ let slots_t_al_v (#t : Type0) (slots : slots_t t) : assoc_list t =
/// list per slot). This is the representation we use most, internally. Note that
/// we later introduce a [map_s] representation, which is the one used in the
/// lemmas shown to the user.
-type hash_map_slots_s t = list (slot_s t)
-
-/// High-level type for the hash-map, seen as a an associative list
-type hash_map_s t = assoc_list t
+type hash_map_s t = list (slot_s t)
// 'nes': "non-empty slots"
-type hash_map_slots_s_nes (t : Type0) : Type0 =
- hm:hash_map_slots_s t{is_pos_usize (length hm)}
+type hash_map_s_nes (t : Type0) : Type0 =
+ hm:hash_map_s t{is_pos_usize (length hm)}
/// Representation function for [hash_map_t] as a list of slots
-let hash_map_t_v (#t : Type0) (hm : hash_map_t t) : hash_map_slots_s t =
+let hash_map_t_v (#t : Type0) (hm : hash_map_t t) : hash_map_s t =
map list_t_v hm.hash_map_slots
/// Representation function for [hash_map_t] as an associative list
-let hash_map_t_al_v (#t : Type0) (hm : hash_map_t t) : hash_map_s t =
+let hash_map_t_al_v (#t : Type0) (hm : hash_map_t t) : assoc_list t =
flatten (hash_map_t_v hm)
// 'nes': "non-empty slots"
@@ -491,36 +489,34 @@ let binding_neq (#t : Type0) (b0 b1 : binding t) : bool = fst b0 <> fst b1
let hash_map_t_len_s (#t : Type0) (hm : hash_map_t t) : nat =
hm.hash_map_num_entries
-let slot_s_find (#t : Type0) (k : key) (slot : list (binding t)) : option t =
+let assoc_list_find (#t : Type0) (k : key) (slot : assoc_list t) : option t =
match find (same_key k) slot with
| None -> None
| Some (_, v) -> Some v
-let assoc_list_find (#t : Type0) (k : key) (slot : assoc_list t) : option t =
- slot_s_find k slot
+let slot_s_find (#t : Type0) (k : key) (slot : list (binding t)) : option t =
+ assoc_list_find k slot
let slot_t_find_s (#t : Type0) (k : key) (slot : list_t t) : option t =
- match find (same_key k) (list_t_v slot) with
- | None -> None
- | Some (_, v) -> Some v
+ slot_s_find k (slot_t_v slot)
// This is a simpler version of the "find" function, which captures the essence
-// of what happens and operates on [hash_map_slots_s].
-let hash_map_slots_s_find
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+// of what happens and operates on [hash_map_s].
+let hash_map_s_find
+ (#t : Type0) (hm : hash_map_s_nes t)
(k : key) : option t =
let i = hash_mod_key k (length hm) in
let slot = index hm i in
slot_s_find k slot
-let hash_map_slots_s_len
- (#t : Type0) (hm : hash_map_slots_s_nes t) :
+let hash_map_s_len
+ (#t : Type0) (hm : hash_map_s_nes t) :
nat =
length (flatten hm)
// Same as above, but operates on [hash_map_t]
// Note that we don't reuse the above function on purpose: converting to a
-// [hash_map_slots_s] then looking up an element is not the same as what we
+// [hash_map_s] then looking up an element is not the same as what we
// wrote below.
let hash_map_t_find_s
(#t : Type0) (hm : hash_map_t t{length hm.hash_map_slots > 0}) (k : key) : option t =
@@ -539,22 +535,20 @@ let slot_s_inv
pairwise_rel binding_neq slot
let slot_t_inv (#t : Type0) (len : usize{len > 0}) (i : usize) (slot : list_t t) : bool =
- // All the bindings are in the proper slot
- for_all (same_hash_mod_key len i) (list_t_v slot) &&
- // All the keys are pairwise distinct
- pairwise_rel binding_neq (list_t_v slot)
+ slot_s_inv len i (slot_t_v slot)
let slots_s_inv (#t : Type0) (slots : slots_s t{length slots <= usize_max}) : Type0 =
forall(i:nat{i < length slots}).
{:pattern index slots i}
slot_s_inv (length slots) i (index slots i)
+// TODO: write that in terms of slots_s_inv
let slots_t_inv (#t : Type0) (slots : slots_t t{length slots <= usize_max}) : Type0 =
forall(i:nat{i < length slots}).
{:pattern index slots i}
slot_t_inv (length slots) i (index slots i)
-let hash_map_slots_s_inv (#t : Type0) (hm : hash_map_slots_s t) : Type0 =
+let hash_map_s_inv (#t : Type0) (hm : hash_map_s t) : Type0 =
length hm <= usize_max /\
length hm > 0 /\
slots_s_inv hm
@@ -1254,14 +1248,14 @@ let hash_map_insert_in_list_back_lem t len key value ls =
(**** Refinement proof *)
/// Same strategy as for [insert_in_list]: we introduce a high-level version of
/// the function, and reason about it.
-/// We work on [hash_map_slots_s] (we use a higher-level view of the hash-map, but
+/// We work on [hash_map_s] (we use a higher-level view of the hash-map, but
/// not too high).
/// A high-level version of insert, which doesn't check if the table is saturated
let hash_map_insert_no_fail_s
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(key : usize) (value : t) :
- hash_map_slots_s t =
+ hash_map_s t =
let len = length hm in
let i = hash_mod_key key len in
let slot = index hm i in
@@ -1269,14 +1263,14 @@ let hash_map_insert_no_fail_s
let hm' = list_update hm i slot' in
hm'
-// TODO: at some point I used hash_map_slots_s_nes and it broke proofs...x
+// TODO: at some point I used hash_map_s_nes and it broke proofs...x
let hash_map_insert_no_resize_s
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(key : usize) (value : t) :
- result (hash_map_slots_s t) =
+ result (hash_map_s t) =
// Check if the table is saturated (too many entries, and we need to insert one)
let num_entries = length (flatten hm) in
- if None? (hash_map_slots_s_find hm key) && num_entries = usize_max then Fail
+ if None? (hash_map_s_find hm key) && num_entries = usize_max then Fail
else Return (hash_map_insert_no_fail_s hm key value)
/// Prove that [hash_map_insert_no_resize_s] is refined by
@@ -1286,7 +1280,7 @@ val hash_map_insert_no_resize_fwd_back_lem_s
Lemma
(requires (
hash_map_t_base_inv self /\
- hash_map_slots_s_len (hash_map_t_v self) = hash_map_t_len_s self))
+ hash_map_s_len (hash_map_t_v self) = hash_map_t_len_s self))
(ensures (
begin
match hash_map_insert_no_resize_fwd_back t self key value,
@@ -1297,7 +1291,7 @@ val hash_map_insert_no_resize_fwd_back_lem_s
hash_map_t_base_inv hm /\
hash_map_same_params hm self /\
hash_map_t_v hm == hm_v /\
- hash_map_slots_s_len hm_v == hash_map_t_len_s hm
+ hash_map_s_len hm_v == hash_map_t_len_s hm
| _ -> False
end))
@@ -1345,7 +1339,7 @@ let hash_map_insert_no_resize_fwd_back_lem_s t self key value =
assert_norm(length [(key,value)] = 1);
assert(length (list_t_v l0) = length (list_t_v l) + 1);
length_flatten_update self_v hash_mod (list_t_v l0);
- assert(hash_map_slots_s_len hm_v = hash_map_t_len_s hm)
+ assert(hash_map_s_len hm_v = hash_map_t_len_s hm)
end
end
end
@@ -1363,7 +1357,7 @@ let hash_map_insert_no_resize_fwd_back_lem_s t self key value =
assert(hm_v == list_update self_v hash_mod (list_t_v l0));
assert(length (list_t_v l0) = length (list_t_v l));
length_flatten_update self_v hash_mod (list_t_v l0);
- assert(hash_map_slots_s_len hm_v = hash_map_t_len_s hm)
+ assert(hash_map_s_len hm_v = hash_map_t_len_s hm)
end
end
end
@@ -1373,30 +1367,30 @@ let hash_map_insert_no_resize_fwd_back_lem_s t self key value =
(**** insert_{no_fail,no_resize}: invariants *)
-let hash_map_slots_s_updated_binding
- (#t : Type0) (hm : hash_map_slots_s_nes t)
- (key : usize) (opt_value : option t) (hm' : hash_map_slots_s_nes t) : Type0 =
+let hash_map_s_updated_binding
+ (#t : Type0) (hm : hash_map_s_nes t)
+ (key : usize) (opt_value : option t) (hm' : hash_map_s_nes t) : Type0 =
// [key] maps to [value]
- hash_map_slots_s_find hm' key == opt_value /\
+ hash_map_s_find hm' key == opt_value /\
// The other bindings are preserved
- (forall k'. k' <> key ==> hash_map_slots_s_find hm' k' == hash_map_slots_s_find hm k')
+ (forall k'. k' <> key ==> hash_map_s_find hm' k' == hash_map_s_find hm k')
-let insert_post (#t : Type0) (hm : hash_map_slots_s_nes t)
- (key : usize) (value : t) (hm' : hash_map_slots_s_nes t) : Type0 =
+let insert_post (#t : Type0) (hm : hash_map_s_nes t)
+ (key : usize) (value : t) (hm' : hash_map_s_nes t) : Type0 =
// The invariant is preserved
- hash_map_slots_s_inv hm' /\
+ hash_map_s_inv hm' /\
// [key] maps to [value] and the other bindings are preserved
- hash_map_slots_s_updated_binding hm key (Some value) hm' /\
+ hash_map_s_updated_binding hm key (Some value) hm' /\
// The length is incremented, iff we inserted a new key
- (match hash_map_slots_s_find hm key with
- | None -> hash_map_slots_s_len hm' = hash_map_slots_s_len hm + 1
- | Some _ -> hash_map_slots_s_len hm' = hash_map_slots_s_len hm)
+ (match hash_map_s_find hm key with
+ | None -> hash_map_s_len hm' = hash_map_s_len hm + 1
+ | Some _ -> hash_map_s_len hm' = hash_map_s_len hm)
val hash_map_insert_no_fail_s_lem
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(key : usize) (value : t) :
Lemma
- (requires (hash_map_slots_s_inv hm))
+ (requires (hash_map_s_inv hm))
(ensures (
let hm' = hash_map_insert_no_fail_s hm key value in
insert_post hm key value hm'))
@@ -1410,23 +1404,23 @@ let hash_map_insert_no_fail_s_lem #t hm key value =
length_flatten_update hm i slot'
val hash_map_insert_no_resize_s_lem
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(key : usize) (value : t) :
Lemma
- (requires (hash_map_slots_s_inv hm))
+ (requires (hash_map_s_inv hm))
(ensures (
match hash_map_insert_no_resize_s hm key value with
| Fail ->
// Can fail only if we need to create a new binding in
// an already saturated map
- hash_map_slots_s_len hm = usize_max /\
- None? (hash_map_slots_s_find hm key)
+ hash_map_s_len hm = usize_max /\
+ None? (hash_map_s_find hm key)
| Return hm' ->
insert_post hm key value hm'))
let hash_map_insert_no_resize_s_lem #t hm key value =
let num_entries = length (flatten hm) in
- if None? (hash_map_slots_s_find hm key) && num_entries = usize_max then ()
+ if None? (hash_map_s_find hm key) && num_entries = usize_max then ()
else hash_map_insert_no_fail_s_lem hm key value
@@ -1434,18 +1428,18 @@ let hash_map_insert_no_resize_s_lem #t hm key value =
/// Lemmas about what happens if we call [find] after an insertion
val hash_map_insert_no_resize_s_get_same_lem
- (#t : Type0) (hm : hash_map_slots_s t)
+ (#t : Type0) (hm : hash_map_s t)
(key : usize) (value : t) :
- Lemma (requires (hash_map_slots_s_inv hm))
+ Lemma (requires (hash_map_s_inv hm))
(ensures (
match hash_map_insert_no_resize_s hm key value with
| Fail -> True
| Return hm' ->
- hash_map_slots_s_find hm' key == Some value))
+ hash_map_s_find hm' key == Some value))
let hash_map_insert_no_resize_s_get_same_lem #t hm key value =
let num_entries = length (flatten hm) in
- if None? (hash_map_slots_s_find hm key) && num_entries = usize_max then ()
+ if None? (hash_map_s_find hm key) && num_entries = usize_max then ()
else
begin
let hm' = Return?.v (hash_map_insert_no_resize_s hm key value) in
@@ -1456,18 +1450,18 @@ let hash_map_insert_no_resize_s_get_same_lem #t hm key value =
end
val hash_map_insert_no_resize_s_get_diff_lem
- (#t : Type0) (hm : hash_map_slots_s t)
+ (#t : Type0) (hm : hash_map_s t)
(key : usize) (value : t) (key' : usize{key' <> key}) :
- Lemma (requires (hash_map_slots_s_inv hm))
+ Lemma (requires (hash_map_s_inv hm))
(ensures (
match hash_map_insert_no_resize_s hm key value with
| Fail -> True
| Return hm' ->
- hash_map_slots_s_find hm' key' == hash_map_slots_s_find hm key'))
+ hash_map_s_find hm' key' == hash_map_s_find hm key'))
let hash_map_insert_no_resize_s_get_diff_lem #t hm key value key' =
let num_entries = length (flatten hm) in
- if None? (hash_map_slots_s_find hm key) && num_entries = usize_max then ()
+ if None? (hash_map_s_find hm key) && num_entries = usize_max then ()
else
begin
let hm' = Return?.v (hash_map_insert_no_resize_s hm key value) in
@@ -1486,24 +1480,24 @@ let hash_map_insert_no_resize_s_get_diff_lem #t hm key value key' =
(*** move_elements_from_list *)
-/// Having a great time here: if we use `result (hash_map_slots_s_res t)` as the
+/// Having a great time here: if we use `result (hash_map_s_res t)` as the
/// return type for [hash_map_move_elements_from_list_s] instead of having this
/// awkward match, the proof of [hash_map_move_elements_fwd_back_lem_refin] fails.
/// I guess it comes from F*'s poor subtyping.
-/// Followingly, I'm not taking any chance and using [result_hash_map_slots_s]
+/// Followingly, I'm not taking any chance and using [result_hash_map_s]
/// everywhere.
-type result_hash_map_slots_s_nes (t : Type0) : Type0 =
- res:result (hash_map_slots_s t) {
+type result_hash_map_s_nes (t : Type0) : Type0 =
+ res:result (hash_map_s t) {
match res with
| Fail -> True
| Return hm -> is_pos_usize (length hm)
}
let rec hash_map_move_elements_from_list_s
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(ls : slot_s t) :
- // Do *NOT* use `result (hash_map_slots_s t)`
- Tot (result_hash_map_slots_s_nes t)
+ // Do *NOT* use `result (hash_map_s t)`
+ Tot (result_hash_map_s_nes t)
(decreases ls) =
match ls with
| [] -> Return hm
@@ -1609,9 +1603,9 @@ let rec hash_map_move_elements_s_simpl
// only the new hash map in which we moved the elements from the slots):
// this returned value is not used.
let rec hash_map_move_elements_s
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(slots : slots_s t) (i : usize{i <= length slots /\ length slots <= usize_max}) :
- Tot (result_hash_map_slots_s_nes t)
+ Tot (result_hash_map_s_nes t)
(decreases (length slots - i)) =
let len = length slots in
if i < len then
@@ -1645,7 +1639,7 @@ val hash_map_move_elements_fwd_back_lem_refin
// This proof was super unstable for some reasons.
//
-// For instance, using the [hash_map_slots_s_nes] type abbreviation
+// For instance, using the [hash_map_s_nes] type abbreviation
// in some of the above definitions led to a failure (while it was just a type
// abbreviation: the signatures were the same if we unfolded this type). This
// behaviour led me to the hypothesis that maybe it made F*'s type inference
@@ -1740,9 +1734,9 @@ let rec hash_map_move_elements_fwd_back_lem_refin t ntable slots i =
/// as a "flat" associative list (and not a list of lists)
/// This is actually exactly [hash_map_move_elements_from_list_s]...
let rec hash_map_move_elements_s_flat
- (#t : Type0) (ntable : hash_map_slots_s_nes t)
- (slots : hash_map_s t) :
- Tot (result_hash_map_slots_s_nes t)
+ (#t : Type0) (ntable : hash_map_s_nes t)
+ (slots : assoc_list t) :
+ Tot (result_hash_map_s_nes t)
(decreases slots) =
match slots with
| [] -> Return ntable
@@ -1835,7 +1829,7 @@ let rec flatten_nil_prefix_as_flatten_i #a l i =
/// The proof is trivial, the functions are the same.
/// Just keeping two definitions to allow changes...
val hash_map_move_elements_from_list_s_as_flat_lem
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(ls : slot_s t) :
Lemma
(ensures (
@@ -1856,8 +1850,8 @@ let rec hash_map_move_elements_from_list_s_as_flat_lem #t hm ls =
/// Composition of two calls to [hash_map_move_elements_s_flat]
let hash_map_move_elements_s_flat_comp
- (#t : Type0) (hm : hash_map_slots_s_nes t) (slot0 slot1 : slot_s t) :
- Tot (result_hash_map_slots_s_nes t) =
+ (#t : Type0) (hm : hash_map_s_nes t) (slot0 slot1 : slot_s t) :
+ Tot (result_hash_map_s_nes t) =
match hash_map_move_elements_s_flat hm slot0 with
| Fail -> Fail
| Return hm1 -> hash_map_move_elements_s_flat hm1 slot1
@@ -1865,7 +1859,7 @@ let hash_map_move_elements_s_flat_comp
/// High-level desc:
/// move_elements (move_elements hm slot0) slo1 == move_elements hm (slot0 @ slot1)
val hash_map_move_elements_s_flat_append_lem
- (#t : Type0) (hm : hash_map_slots_s_nes t) (slot0 slot1 : slot_s t) :
+ (#t : Type0) (hm : hash_map_s_nes t) (slot0 slot1 : slot_s t) :
Lemma
(ensures (
match hash_map_move_elements_s_flat_comp hm slot0 slot1,
@@ -1907,7 +1901,7 @@ let rec flatten_i_same_suffix #a l0 l1 i =
/// [hash_map_move_elements_s] refines [hash_map_move_elements_s_flat]
/// (actually the functions are equal on all inputs).
val hash_map_move_elements_s_lem_refin_flat
- (#t : Type0) (hm : hash_map_slots_s_nes t)
+ (#t : Type0) (hm : hash_map_s_nes t)
(slots : slots_s t)
(i : nat{i <= length slots /\ length slots <= usize_max}) :
Lemma
@@ -1947,21 +1941,21 @@ let assoc_list_inv (#t : Type0) (al : assoc_list t) : Type0 =
pairwise_rel binding_neq al
let disjoint_hm_al_on_key
- (#t : Type0) (hm : hash_map_slots_s_nes t) (al : assoc_list t) (k : key) : Type0 =
- match hash_map_slots_s_find hm k, assoc_list_find k al with
+ (#t : Type0) (hm : hash_map_s_nes t) (al : assoc_list t) (k : key) : Type0 =
+ match hash_map_s_find hm k, assoc_list_find k al with
| Some _, None
| None, Some _
| None, None -> True
| Some _, Some _ -> False
/// Playing a dangerous game here: using forall quantifiers
-let disjoint_hm_al (#t : Type0) (hm : hash_map_slots_s_nes t) (al : assoc_list t) : Type0 =
+let disjoint_hm_al (#t : Type0) (hm : hash_map_s_nes t) (al : assoc_list t) : Type0 =
forall (k:key). disjoint_hm_al_on_key hm al k
let find_in_union_hm_al
- (#t : Type0) (hm : hash_map_slots_s_nes t) (al : assoc_list t) (k : key) :
+ (#t : Type0) (hm : hash_map_s_nes t) (al : assoc_list t) (k : key) :
option t =
- match hash_map_slots_s_find hm k with
+ match hash_map_s_find hm k with
| Some b -> Some b
| None -> assoc_list_find k al
@@ -1978,25 +1972,25 @@ let rec for_all_binding_neq_find_lem #t k v al =
#pop-options
val hash_map_move_elements_s_flat_lem
- (#t : Type0) (hm : hash_map_slots_s_nes t) (al : assoc_list t) :
+ (#t : Type0) (hm : hash_map_s_nes t) (al : assoc_list t) :
Lemma
(requires (
// Invariants
- hash_map_slots_s_inv hm /\
+ hash_map_s_inv hm /\
assoc_list_inv al /\
// The two are disjoint
disjoint_hm_al hm al /\
// We can add all the elements to the hashmap
- hash_map_slots_s_len hm + length al <= usize_max))
+ hash_map_s_len hm + length al <= usize_max))
(ensures (
match hash_map_move_elements_s_flat hm al with
| Fail -> False // We can't fail
| Return hm' ->
// The invariant is preserved
- hash_map_slots_s_inv hm' /\
+ hash_map_s_inv hm' /\
// The new hash map is the union of the two maps
- (forall (k:key). hash_map_slots_s_find hm' k == find_in_union_hm_al hm al k) /\
- hash_map_slots_s_len hm' = hash_map_slots_s_len hm + length al))
+ (forall (k:key). hash_map_s_find hm' k == find_in_union_hm_al hm al k) /\
+ hash_map_s_len hm' = hash_map_s_len hm + length al))
(decreases al)
#restart-solver
@@ -2009,25 +2003,25 @@ let rec hash_map_move_elements_s_flat_lem #t hm al =
match hash_map_insert_no_resize_s hm k v with
| Fail -> ()
| Return hm' ->
- assert(hash_map_slots_s_inv hm');
+ assert(hash_map_s_inv hm');
assert(assoc_list_inv al');
let disjoint_lem (k' : key) :
Lemma (disjoint_hm_al_on_key hm' al' k')
[SMTPat (disjoint_hm_al_on_key hm' al' k')] =
if k' = k then
begin
- assert(hash_map_slots_s_find hm' k' == Some v);
+ assert(hash_map_s_find hm' k' == Some v);
for_all_binding_neq_find_lem k v al';
assert(assoc_list_find k' al' == None)
end
else
begin
- assert(hash_map_slots_s_find hm' k' == hash_map_slots_s_find hm k');
+ assert(hash_map_s_find hm' k' == hash_map_s_find hm k');
assert(assoc_list_find k' al' == assoc_list_find k' al)
end
in
assert(disjoint_hm_al hm' al');
- assert(hash_map_slots_s_len hm' + length al' <= usize_max);
+ assert(hash_map_s_len hm' + length al' <= usize_max);
hash_map_move_elements_s_flat_lem hm' al'
#pop-options
@@ -2044,18 +2038,18 @@ let slots_t_inv_implies_slots_s_inv #t slots =
// Problem is: I can never really predict for sure with F*...
()
-val hash_map_t_base_inv_implies_hash_map_slots_s_inv
+val hash_map_t_base_inv_implies_hash_map_s_inv
(#t : Type0) (hm : hash_map_t t) :
Lemma (requires (hash_map_t_base_inv hm))
- (ensures (hash_map_slots_s_inv (hash_map_t_v hm)))
+ (ensures (hash_map_s_inv (hash_map_t_v hm)))
-let hash_map_t_base_inv_implies_hash_map_slots_s_inv #t hm = () // same as previous
+let hash_map_t_base_inv_implies_hash_map_s_inv #t hm = () // same as previous
/// Introducing a "partial" version of the hash map invariant, which operates on
/// a suffix of the hash map.
-let partial_hash_map_slots_s_inv
+let partial_hash_map_s_inv
(#t : Type0) (len : usize{len > 0}) (offset : usize)
- (hm : hash_map_slots_s t{offset + length hm <= usize_max}) : Type0 =
+ (hm : hash_map_s t{offset + length hm <= usize_max}) : Type0 =
forall(i:nat{i < length hm}). {:pattern index hm i} slot_s_inv len (offset + i) (index hm i)
/// Auxiliary lemma.
@@ -2065,13 +2059,13 @@ val binding_in_previous_slot_implies_neq
(#t : Type0) (len : usize{len > 0})
(i : usize) (b : binding t)
(offset : usize{i < offset})
- (slots : hash_map_slots_s t{offset + length slots <= usize_max}) :
+ (slots : hash_map_s t{offset + length slots <= usize_max}) :
Lemma
(requires (
// The binding comes from a slot not in [slots]
hash_mod_key (fst b) len = i /\
// The slots are the well-formed suffix of a hash map
- partial_hash_map_slots_s_inv len offset slots))
+ partial_hash_map_s_inv len offset slots))
(ensures (
for_all (binding_neq b) (flatten slots)))
(decreases slots)
@@ -2102,17 +2096,17 @@ let rec binding_in_previous_slot_implies_neq #t len i b offset slots =
for_all_append (binding_neq b) s (flatten slots')
#pop-options
-val partial_hash_map_slots_s_inv_implies_assoc_list_lem
+val partial_hash_map_s_inv_implies_assoc_list_lem
(#t : Type0) (len : usize{len > 0}) (offset : usize)
- (hm : hash_map_slots_s t{offset + length hm <= usize_max}) :
+ (hm : hash_map_s t{offset + length hm <= usize_max}) :
Lemma
(requires (
- partial_hash_map_slots_s_inv len offset hm))
+ partial_hash_map_s_inv len offset hm))
(ensures (assoc_list_inv (flatten hm)))
(decreases (length hm + length (flatten hm)))
#push-options "--fuel 1"
-let rec partial_hash_map_slots_s_inv_implies_assoc_list_lem #t len offset hm =
+let rec partial_hash_map_s_inv_implies_assoc_list_lem #t len offset hm =
match hm with
| [] -> ()
| slot :: hm' ->
@@ -2121,8 +2115,8 @@ let rec partial_hash_map_slots_s_inv_implies_assoc_list_lem #t len offset hm =
match slot with
| [] ->
assert(flatten hm == flatten hm');
- assert(partial_hash_map_slots_s_inv len (offset+1) hm'); // Triggers instantiations
- partial_hash_map_slots_s_inv_implies_assoc_list_lem len (offset+1) hm'
+ assert(partial_hash_map_s_inv len (offset+1) hm'); // Triggers instantiations
+ partial_hash_map_s_inv_implies_assoc_list_lem len (offset+1) hm'
| x :: slot' ->
assert(flatten (slot' :: hm') == slot' @ flatten hm');
let hm'' = slot' :: hm' in
@@ -2131,25 +2125,25 @@ let rec partial_hash_map_slots_s_inv_implies_assoc_list_lem #t len offset hm =
assert(index hm 0 == slot); // Triggers instantiations
assert(slot_s_inv len offset slot);
assert(slot_s_inv len offset slot');
- assert(partial_hash_map_slots_s_inv len offset hm'');
- partial_hash_map_slots_s_inv_implies_assoc_list_lem len offset (slot' :: hm');
+ assert(partial_hash_map_s_inv len offset hm'');
+ partial_hash_map_s_inv_implies_assoc_list_lem len offset (slot' :: hm');
// Proving that the key in `x` is different from all the other keys in
// the flattened map
assert(for_all (binding_neq x) slot');
for_all_append (binding_neq x) slot' (flatten hm');
- assert(partial_hash_map_slots_s_inv len (offset+1) hm');
+ assert(partial_hash_map_s_inv len (offset+1) hm');
binding_in_previous_slot_implies_neq #t len offset x (offset+1) hm';
assert(for_all (binding_neq x) (flatten hm'));
assert(for_all (binding_neq x) (flatten (slot' :: hm')))
#pop-options
-val hash_map_slots_s_inv_implies_assoc_list_lem
- (#t : Type0) (hm : hash_map_slots_s t) :
- Lemma (requires (hash_map_slots_s_inv hm))
+val hash_map_s_inv_implies_assoc_list_lem
+ (#t : Type0) (hm : hash_map_s t) :
+ Lemma (requires (hash_map_s_inv hm))
(ensures (assoc_list_inv (flatten hm)))
-let hash_map_slots_s_inv_implies_assoc_list_lem #t hm =
- partial_hash_map_slots_s_inv_implies_assoc_list_lem (length hm) 0 hm
+let hash_map_s_inv_implies_assoc_list_lem #t hm =
+ partial_hash_map_s_inv_implies_assoc_list_lem (length hm) 0 hm
val hash_map_t_base_inv_implies_assoc_list_lem
(#t : Type0) (hm : hash_map_t t):
@@ -2157,7 +2151,7 @@ val hash_map_t_base_inv_implies_assoc_list_lem
(ensures (assoc_list_inv (hash_map_t_al_v hm)))
let hash_map_t_base_inv_implies_assoc_list_lem #t hm =
- hash_map_slots_s_inv_implies_assoc_list_lem (hash_map_t_v hm)
+ hash_map_s_inv_implies_assoc_list_lem (hash_map_t_v hm)
/// For some reason, we can't write the below [forall] directly in the [ensures]
/// clause of the next lemma: it makes Z3 fails even with a huge rlimit.
@@ -2167,9 +2161,9 @@ let hash_map_is_assoc_list
(al : assoc_list t) : Type0 =
(forall (k:key). hash_map_t_find_s ntable k == assoc_list_find k al)
-let partial_hash_map_slots_s_find
+let partial_hash_map_s_find
(#t : Type0) (len : usize{len > 0}) (offset : usize)
- (hm : hash_map_slots_s_nes t{offset + length hm = len})
+ (hm : hash_map_s_nes t{offset + length hm = len})
(k : key{hash_mod_key k len >= offset}) : option t =
let i = hash_mod_key k len in
let slot = index hm (i - offset) in
@@ -2199,13 +2193,13 @@ val key_in_previous_slot_implies_not_found
(#t : Type0) (len : usize{len > 0})
(k : key)
(offset : usize)
- (slots : hash_map_slots_s t{offset + length slots = len}) :
+ (slots : hash_map_s t{offset + length slots = len}) :
Lemma
(requires (
// The binding comes from a slot not in [slots]
hash_mod_key k len < offset /\
// The slots are the well-formed suffix of a hash map
- partial_hash_map_slots_s_inv len offset slots))
+ partial_hash_map_s_inv len offset slots))
(ensures (
assoc_list_find k (flatten slots) == None))
(decreases slots)
@@ -2223,20 +2217,20 @@ let rec key_in_previous_slot_implies_not_found #t len k offset slots =
key_in_previous_slot_implies_not_found len k (offset+1) slots'
#pop-options
-val partial_hash_map_slots_s_is_assoc_list_lem
+val partial_hash_map_s_is_assoc_list_lem
(#t : Type0) (len : usize{len > 0}) (offset : usize)
- (hm : hash_map_slots_s_nes t{offset + length hm = len})
+ (hm : hash_map_s_nes t{offset + length hm = len})
(k : key{hash_mod_key k len >= offset}) :
Lemma
(requires (
- partial_hash_map_slots_s_inv len offset hm))
+ partial_hash_map_s_inv len offset hm))
(ensures (
- partial_hash_map_slots_s_find len offset hm k == assoc_list_find k (flatten hm)))
+ partial_hash_map_s_find len offset hm k == assoc_list_find k (flatten hm)))
(decreases hm)
// (decreases (length hm + length (flatten hm)))
#push-options "--fuel 1"
-let rec partial_hash_map_slots_s_is_assoc_list_lem #t len offset hm k =
+let rec partial_hash_map_s_is_assoc_list_lem #t len offset hm k =
match hm with
| [] -> ()
| slot :: hm' ->
@@ -2245,7 +2239,7 @@ let rec partial_hash_map_slots_s_is_assoc_list_lem #t len offset hm k =
if i = 0 then
begin
// We must look in the current slot
- assert(partial_hash_map_slots_s_find len offset hm k == slot_s_find k slot);
+ assert(partial_hash_map_s_find len offset hm k == slot_s_find k slot);
find_append (same_key k) slot (flatten hm');
assert(forall (i:nat{i < length hm'}). index hm' i == index hm (i+1)); // Triggers instantiations
key_in_previous_slot_implies_not_found #t len k (offset+1) hm';
@@ -2264,13 +2258,13 @@ let rec partial_hash_map_slots_s_is_assoc_list_lem #t len offset hm k =
else
begin
// We must ignore the current slot
- assert(partial_hash_map_slots_s_find len offset hm k ==
- partial_hash_map_slots_s_find len (offset+1) hm' k);
+ assert(partial_hash_map_s_find len offset hm k ==
+ partial_hash_map_s_find len (offset+1) hm' k);
find_append (same_key k) slot (flatten hm');
assert(index hm 0 == slot); // Triggers instantiations
not_same_hash_key_not_found_in_slot #t len k offset slot;
assert(forall (i:nat{i < length hm'}). index hm' i == index hm (i+1)); // Triggers instantiations
- partial_hash_map_slots_s_is_assoc_list_lem #t len (offset+1) hm' k
+ partial_hash_map_s_is_assoc_list_lem #t len (offset+1) hm' k
end
#pop-options
@@ -2284,7 +2278,7 @@ let hash_map_is_assoc_list_lem #t hm =
[SMTPat (hash_map_t_find_s hm k)] =
let hm_v = hash_map_t_v hm in
let len = length hm_v in
- partial_hash_map_slots_s_is_assoc_list_lem #t len 0 hm_v k
+ partial_hash_map_s_is_assoc_list_lem #t len 0 hm_v k
in
()
@@ -2669,7 +2663,7 @@ val hash_map_insert_fwd_back_lem
// The invariant is preserved
hash_map_t_inv hm' /\
// [key] maps to [value] and the other bindings are preserved
- hash_map_slots_s_updated_binding (hash_map_t_v self) key (Some value) (hash_map_t_v hm') /\
+ hash_map_s_updated_binding (hash_map_t_v self) key (Some value) (hash_map_t_v hm') /\
// The length is incremented, iff we inserted a new key
(match hash_map_t_find_s self key with
| None -> hash_map_t_len_s hm' = hash_map_t_len_s self + 1
@@ -2680,11 +2674,11 @@ let hash_map_insert_fwd_back_bindings_lem
(hm' hm'' : hash_map_t_nes t) :
Lemma
(requires (
- hash_map_slots_s_updated_binding (hash_map_t_v self) key
+ hash_map_s_updated_binding (hash_map_t_v self) key
(Some value) (hash_map_t_v hm') /\
hash_map_t_same_bindings hm' hm''))
(ensures (
- hash_map_slots_s_updated_binding (hash_map_t_v self) key
+ hash_map_s_updated_binding (hash_map_t_v self) key
(Some value) (hash_map_t_v hm'')))
= ()
@@ -2702,15 +2696,15 @@ let hash_map_insert_fwd_back_lem t self key value =
assert(hash_map_t_base_inv hm');
assert(hash_map_same_params hm' self);
assert(hash_map_t_v hm' == hm'_v);
- assert(hash_map_slots_s_len hm'_v == hash_map_t_len_s hm');
+ assert(hash_map_s_len hm'_v == hash_map_t_len_s hm');
// Expanding the post of [hash_map_insert_no_resize_s_lem]
assert(insert_post self_v key value hm'_v);
// Expanding [insert_post]
- assert(hash_map_slots_s_inv hm'_v);
+ assert(hash_map_s_inv hm'_v);
assert(
- match hash_map_slots_s_find self_v key with
- | None -> hash_map_slots_s_len hm'_v = hash_map_slots_s_len self_v + 1
- | Some _ -> hash_map_slots_s_len hm'_v = hash_map_slots_s_len self_v);
+ match hash_map_s_find self_v key with
+ | None -> hash_map_s_len hm'_v = hash_map_s_len self_v + 1
+ | Some _ -> hash_map_s_len hm'_v = hash_map_s_len self_v);
if hash_map_t_len_s hm' > hm'.hash_map_max_load then
begin
hash_map_try_resize_fwd_back_lem hm';
@@ -3166,8 +3160,8 @@ let rec hash_map_remove_from_list_back_lem_refin #t key ls =
/// High-level model for [remove_from_list'back]
let hash_map_remove_s
- (#t : Type0) (self : hash_map_slots_s_nes t) (key : usize) :
- hash_map_slots_s t =
+ (#t : Type0) (self : hash_map_s_nes t) (key : usize) :
+ hash_map_s t =
let len = length self in
let hash = hash_mod_key key len in
let slot = index self hash in
@@ -3293,15 +3287,15 @@ let rec hash_map_remove_from_list_s_lem #t key slot len i =
#pop-options
val hash_map_remove_s_lem
- (#t : Type0) (self : hash_map_slots_s_nes t) (key : usize) :
+ (#t : Type0) (self : hash_map_s_nes t) (key : usize) :
Lemma
- (requires (hash_map_slots_s_inv self))
+ (requires (hash_map_s_inv self))
(ensures (
let hm' = hash_map_remove_s self key in
// The invariant is preserved
- hash_map_slots_s_inv hm' /\
+ hash_map_s_inv hm' /\
// We updated the binding
- hash_map_slots_s_updated_binding self key None hm'))
+ hash_map_s_updated_binding self key None hm'))
let hash_map_remove_s_lem #t self key =
let len = length self in
@@ -3310,7 +3304,7 @@ let hash_map_remove_s_lem #t self key =
hash_map_remove_from_list_s_lem key slot len hash;
let slot' = hash_map_remove_from_list_s key slot in
let hm' = list_update self hash slot' in
- assert(hash_map_slots_s_inv self)
+ assert(hash_map_s_inv self)
/// Final lemma about [remove'back]
val hash_map_remove_back_lem