mutable/MBMap
Reference for mo:core/mutable/MBMap in the core library.
MBMap is a mutable facade over the immutable B+tree map. Its contracts keep
a ghost Map<K, V> model attached to the mutable memory object, so updates can
be verified while implementation code uses in-place-style operations.
When V is an opaque/token handle, MBMap stores and returns handle
identities. Its model tracks map structure and key-to-handle facts; it does not
grant payload access or prove that the owner model of a stored handle is stable
after an owner-module mutation.
Import
mo:core/mutable/MBMap
Status
- Mutable module
Public API
Types
Order,Iter,MapMem
Modules
Spec
Functions
model<K, V>(m : MapMem<K, V>) : Map<K, V>
Returns the abstract ghost model used by contracts and lemmas.
For handle values, this is an identity model over the stored handles, not a snapshot of each handle owner's payload.
Contract
ensures result == m.model;
Use when: Use in contracts, ghost code, or lemmas when the runtime value needs an abstract proof model.
orderedBy<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order) : Bool
Checks the predicate described by the return contract.
Contract
ensures result == PureMap.orderedBy<K, V>(m.root, compare);
ensures model<K, V>(m) == Map.empty<K, V>() ==> result;
Use when: code or specifications need this operation with the documented contract.
empty<K, V>() : MapMem<K, V>
Constructs the empty value for this module's data structure.
Contract
ensures model<K, V>(result) == Map.empty<K, V>();
ensures Map.card<K, V>(model<K, V>(result)) == 0;
ensures forall<K>(func (k : K) : Bool =
Map.contains<K, V>(k, model<K, V>(result)) == false);
ensures Prim.abs(Map.card<K, V>(model<K, V>(result))) == 0;
Use when: code or specifications need this operation with the documented contract.
size<K, V>(m : MapMem<K, V>) : Nat
Returns the length or cardinality represented by the value.
Contract
ensures result == PureMap.size<K, V>(m.root);
ensures result == Prim.abs(Map.card<K, V>(model<K, V>(m)));
Use when: code or specifications need this operation with the documented contract.
isEmpty<K, V>(m : MapMem<K, V>) : Bool
Checks the predicate described by the return contract.
Contract
ensures result == PureMap.isEmpty<K, V>(m.root);
ensures result == (Prim.abs(Map.card<K, V>(model<K, V>(m))) == 0);
Use when: a branch condition or contract needs this predicate as a named fact.
get<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K) : ?V
Reads the requested value from the structure.
Contract
requires orderedBy<K, V>(m, compare);
ensures Map.contains<K, V>(key, model<K, V>(m)) == true ==>
result == ?Map.get<K, V>(model<K, V>(m), key);
ensures Map.contains<K, V>(key, model<K, V>(m)) == false ==> result == null;
ensures model<K, V>(m) == old(model<K, V>(m));
ensures orderedBy<K, V>(m, compare);
Use when: reading this value is part of an implementation or postcondition.
contains<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K) : Bool
Checks the predicate described by the return contract.
Contract
requires orderedBy<K, V>(m, compare);
ensures result == Map.contains<K, V>(key, model<K, V>(m));
ensures model<K, V>(m) == old(model<K, V>(m));
ensures orderedBy<K, V>(m, compare);
Use when: a branch condition or contract needs this predicate as a named fact.
getOr<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K, default : V) : V
Reads the requested value from the structure.
Contract
requires orderedBy<K, V>(m, compare);
ensures result == Map.getOr<K, V>(model<K, V>(m), key, default);
ensures model<K, V>(m) == old(model<K, V>(m));
ensures orderedBy<K, V>(m, compare);
Use when: reading this value is part of an implementation or postcondition.
getPresent<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K, default : V) : V
Reads the requested value from the structure.
Contract
requires orderedBy<K, V>(m, compare);
requires Map.contains<K, V>(key, model<K, V>(m));
ensures result == Map.get<K, V>(model<K, V>(m), key);
ensures model<K, V>(m) == old(model<K, V>(m));
ensures orderedBy<K, V>(m, compare);
Use when: reading this value is part of an implementation or postcondition.
add<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K, value : V) : ()
Inserts or replaces the key/value entry while preserving the map model.
Contract
requires orderedBy<K, V>(m, compare);
ensures model<K, V>(m) == Map.update<K, V>(old(model<K, V>(m)), key, value);
ensures Map.contains<K, V>(key, model<K, V>(m));
ensures forall<K>(func (k : K) : Bool =
k != key ==> Map.contains<K, V>(k, model<K, V>(m))
== Map.contains<K, V>(k, old(model<K, V>(m))));
ensures forall<K>(func (k : K) : Bool =
(k != key and Map.contains<K, V>(k, old(model<K, V>(m)))) ==>
Map.get<K, V>(model<K, V>(m), k) == Map.get<K, V>(old(model<K, V>(m)), k));
ensures Map.contains<K, V>(key, old(model<K, V>(m))) == false ==>
Prim.abs(Map.card<K, V>(model<K, V>(m))) ==
Prim.abs(Map.card<K, V>(old(model<K, V>(m)))) + 1;
ensures Map.contains<K, V>(key, old(model<K, V>(m))) == true ==>
Prim.abs(Map.card<K, V>(model<K, V>(m))) ==
Prim.abs(Map.card<K, V>(old(model<K, V>(m))));
ensures orderedBy<K, V>(m, compare);
Use when: the postcondition must relate the updated value to the previous one.
remove<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K) : ()
Returns the updated collection or value described by the contract.
Contract
requires orderedBy<K, V>(m, compare);
ensures model<K, V>(m) == Spec.modelRemove<K, V>(old(model<K, V>(m)), key);
ensures Map.contains<K, V>(key, model<K, V>(m)) == false;
ensures forall<K>(func (k : K) : Bool =
k != key ==> Map.contains<K, V>(k, model<K, V>(m))
== Map.contains<K, V>(k, old(model<K, V>(m))));
ensures forall<K>(func (k : K) : Bool =
(k != key and Map.contains<K, V>(k, old(model<K, V>(m)))) ==>
Map.get<K, V>(model<K, V>(m), k) == Map.get<K, V>(old(model<K, V>(m)), k));
ensures Map.contains<K, V>(key, old(model<K, V>(m))) == false ==>
model<K, V>(m) == old(model<K, V>(m));
ensures Map.contains<K, V>(key, old(model<K, V>(m))) == true ==>
Prim.abs(Map.card<K, V>(old(model<K, V>(m)))) ==
Prim.abs(Map.card<K, V>(model<K, V>(m))) + 1;
ensures Map.contains<K, V>(key, old(model<K, V>(m))) == false ==>
Prim.abs(Map.card<K, V>(model<K, V>(m))) ==
Prim.abs(Map.card<K, V>(old(model<K, V>(m))));
ensures orderedBy<K, V>(m, compare);
Use when: the postcondition must relate the updated value to the previous one.
putOption<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order, key : K, next : ?V) : ()
Returns or applies the corresponding update to the structure.
Contract
requires orderedBy<K, V>(m, compare);
ensures model<K, V>(m) == Spec.modelPutOption<K, V>(old(model<K, V>(m)), key, next);
ensures switch (next) {
case null { Map.contains<K, V>(key, model<K, V>(m)) == false };
case (? value) {
Map.contains<K, V>(key, model<K, V>(m)) and
Map.get<K, V>(model<K, V>(m), key) == value
}
};
ensures forall<K>(func (k : K) : Bool =
k != key ==> Map.contains<K, V>(k, model<K, V>(m))
== Map.contains<K, V>(k, old(model<K, V>(m))));
ensures forall<K>(func (k : K) : Bool =
(k != key and Map.contains<K, V>(k, old(model<K, V>(m)))) ==>
Map.get<K, V>(model<K, V>(m), k) == Map.get<K, V>(old(model<K, V>(m)), k));
ensures orderedBy<K, V>(m, compare);
Use when: the postcondition must relate the updated value to the previous one.
entries<K, V>(m : MapMem<K, V>) : Iter<(K, V)>
Creates an iterator over map entries in forward or reverse order.
Contract
ensures PureMap.Spec.iterKeys<K, V>(result) == Map.domain<K, V>(model<K, V>(m));
ensures PureMap.Spec.iterValues<K, V>(result) == Map.range<K, V>(model<K, V>(m));
ensures Spec.entrySnapshot<K, V>(
PureMap.iterKeysXSeq<K, V>(result),
PureMap.iterValuesXSeq<K, V>(result),
model<K, V>(m)
);
ensures Spec.entryKeysNoDuplicates<K>(PureMap.iterKeysXSeq<K, V>(result));
ensures BSeq.len<K>(PureMap.iterKeysXSeq<K, V>(result)) == size<K, V>(m);
ensures BSeq.len<V>(PureMap.iterValuesXSeq<K, V>(result)) == size<K, V>(m);
ensures model<K, V>(m) == old(model<K, V>(m));
Use when: code or specifications need this operation with the documented contract.
keysXSeq<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order) : BSeq.XSeq<K>
Collects iterator or map keys into a persistent BSeq sequence.
Contract
requires orderedBy<K, V>(m, compare);
ensures result == PureMap.iterKeysXSeq<K, V>(PureMap.entries<K, V>(m.root));
ensures model<K, V>(m) == old(model<K, V>(m));
ensures orderedBy<K, V>(m, compare);
Use when: code or specifications need this operation with the documented contract.
valuesXSeq<K, V>(m : MapMem<K, V>) : BSeq.XSeq<V>
Collects iterator or map values into a persistent BSeq sequence.
Contract
ensures result == PureMap.valuesXSeq<K, V>(m.root);
Use when: code or specifications need this operation with the documented contract.
foldLeft<K, V, A>(m : MapMem<K, V>, base : A, combine : (A, K, V) -> A) : A
Folds the structure by applying the supplied accumulator function.
Contract
ensures result == PureMap.foldLeft<K, V, A>(m.root, base, combine);
ensures size<K, V>(m) == 0 ==> result == base;
Use when: code or specifications need this operation with the documented contract.
foldValues<K, V, A>(m : MapMem<K, V>, base : A, combine : (A, V) -> A) : A
Folds the structure by applying the supplied accumulator function.
Contract
ensures result == PureMap.foldValues<K, V, A>(m.root, base, combine);
ensures result == BSeq.foldLeft<V, A>(valuesXSeq<K, V>(m), base, combine);
ensures size<K, V>(m) == 0 ==> result == base;
Use when: code or specifications need this operation with the documented contract.
Lemmas
orderedBy_model_empty<K, V>(m : MapMem<K, V>, compare : (K, K) -> Order) : ()
Establishes the listed proof facts in the current verification context.
Contract
requires model<K, V>(m) == Map.empty<K, V>();
ensures orderedBy<K, V>(m, compare);
ensures model<K, V>(m) == old(model<K, V>(m));
Use when: a proof needs this fact explicitly and the solver has not derived it automatically.
entrySnapshot_len<K, V>(keys : PureMap.XSeq<K>, values : PureMap.XSeq<V>, snapshot : Map<K, V>) : ()
Establishes the cardinality of a mutable-map entry snapshot against the call-time model value that produced it.
Contract
requires Spec.entrySnapshot<K, V>(keys, values, snapshot);
ensures BSeq.len<K>(keys) == Prim.abs(Map.card<K, V>(snapshot));
ensures BSeq.len<V>(values) == Prim.abs(Map.card<K, V>(snapshot));
Use when: a proof needs the snapshot epoch explicitly instead of the live mutable object.
entrySnapshot_get<K, V>(keys : PureMap.XSeq<K>, values : PureMap.XSeq<V>, snapshot : Map<K, V>, i : Int) : ()
Establishes the key/value pairing for one index of a mutable-map entry snapshot.
Contract
requires Spec.entrySnapshot<K, V>(keys, values, snapshot);
requires i >= 0;
requires i < BSeq.len<K>(keys);
requires i < BSeq.len<V>(values);
ensures Map.contains<K, V>(BSeq.get<K>(keys, i), snapshot);
ensures Map.get<K, V>(snapshot, BSeq.get<K>(keys, i)) ==
BSeq.get<V>(values, i);
Use when: a proof needs to relate enumerated entries to the call-time model.
entrySnapshot_unique_keys<K, V>(keys : PureMap.XSeq<K>, i : Int, j : Int) : ()
Establishes duplicate-free keys for two distinct indices in an entry snapshot.
Contract
requires Spec.entryKeysNoDuplicates<K>(keys);
requires i >= 0;
requires j >= 0;
requires i < BSeq.len<K>(keys);
requires j < BSeq.len<K>(keys);
requires i != j;
ensures BSeq.get<K>(keys, i) != BSeq.get<K>(keys, j);
Use when: a proof needs no-duplicate-key reasoning over enumerated mutable-map entries.
Spec Module
Spec Functions
modelRemove<K, V>(m : Map<K, V>, key : K) : Map<K, V>
Returns the abstract ghost model used by contracts and lemmas.
Contract
ensures Map.contains<K, V>(key, result) == false;
ensures Map.contains<K, V>(key, m) == false ==> result == m;
ensures forall<K>(func (k : K) : Bool =
k != key ==> Map.contains<K, V>(k, result) == Map.contains<K, V>(k, m));
ensures forall<K>(func (k : K) : Bool =
(k != key and Map.contains<K, V>(k, m)) ==>
Map.get<K, V>(result, k) == Map.get<K, V>(m, k));
Use when: Use in contracts, ghost code, or lemmas when the runtime value needs an abstract proof model.
modelPutOption<K, V>(m : Map<K, V>, key : K, next : ?V) : Map<K, V>
Returns the abstract ghost model used by contracts and lemmas.
Contract
ensures switch (next) {
case null { result == modelRemove<K, V>(m, key) };
case (? value) { result == Map.update<K, V>(m, key, value) }
};
ensures switch (next) {
case null { Map.contains<K, V>(key, result) == false };
case (? value) {
Map.contains<K, V>(key, result) and
Map.get<K, V>(result, key) == value
}
};
ensures forall<K>(func (k : K) : Bool =
k != key ==> Map.contains<K, V>(k, result) == Map.contains<K, V>(k, m));
ensures forall<K>(func (k : K) : Bool =
(k != key and Map.contains<K, V>(k, m)) ==>
Map.get<K, V>(result, k) == Map.get<K, V>(m, k));
Use when: Use in contracts, ghost code, or lemmas when the runtime value needs an abstract proof model.
entrySnapshot<K, V>(keys : PureMap.XSeq<K>, values : PureMap.XSeq<V>, snapshot : Map<K, V>) : Bool
Names an exact entry snapshot for the specific call-time Map<K, V> model
captured by MBMap.entries.
Use when: keep mutable-map snapshot facts tied to an explicit model epoch.
entryKeysNoDuplicates<K>(keys : PureMap.XSeq<K>) : Bool
Names the duplicate-free key property of a mutable-map entry snapshot.
Use when: pair this predicate with entrySnapshot_unique_keys.
Summary
- Mutable module under
mo:core/mutable/MBMap. - Exposes 20 public functions and lemmas.
- Includes 4 spec helpers in
Spec.