mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 12:53:53 +00:00
Estimated hours taken: 0.1 Branches: main library/map.m: Bring this module up to date with respect to our coding guidelines: use predmode syntax where relevant. There are no changes in algorithms.
931 lines
30 KiB
Mathematica
931 lines
30 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1993-2004 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: map.m.
|
|
% Main author: fjh, conway.
|
|
% Stability: high.
|
|
%
|
|
% This file provides the 'map' ADT.
|
|
% A map (also known as a dictionary or an associative array) is a collection
|
|
% of (Key, Data) pairs which allows you to look up any Data item given the
|
|
% Key.
|
|
%
|
|
% The implementation is using balanced binary trees, as provided by
|
|
% tree234.m. Virtually all the predicates in this file just
|
|
% forward the work to the corresponding predicate in tree234.m.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module map.
|
|
:- interface.
|
|
:- import_module set, list, assoc_list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type map(_K, _V).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Initialize an empty map.
|
|
:- pred map__init(map(_, _)::uo) is det.
|
|
:- func map__init = (map(K, V)::uo) is det.
|
|
|
|
% Check whether a map is empty.
|
|
:- pred map__is_empty(map(_, _)::in) is semidet.
|
|
|
|
% Check whether map contains key
|
|
:- pred map__contains(map(K, _V)::in, K::in) is semidet.
|
|
|
|
:- pred map__member(map(K, V)::in, K::out, V::out) is nondet.
|
|
|
|
% Search map for key.
|
|
:- pred map__search(map(K, V)::in, K::in, V::out) is semidet.
|
|
:- func map__search(map(K, V), K) = V is semidet.
|
|
|
|
% Search map for key, but abort if search fails.
|
|
:- pred map__lookup(map(K, V)::in, K::in, V::out) is det.
|
|
:- func map__lookup(map(K, V), K) = V.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next lower key instead.
|
|
% Fails if there is no key with the given or lower value.
|
|
:- pred map__lower_bound_search(map(K, V)::in, K::in, K::out, V::out)
|
|
is semidet.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next lower key instead.
|
|
% Aborts if there is no key with the given or lower value.
|
|
:- pred map__lower_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next higher key instead.
|
|
% Fails if there is no key with the given or higher value.
|
|
:- pred map__upper_bound_search(map(K, V)::in, K::in, K::out, V::out)
|
|
is semidet.
|
|
|
|
% Search for a key-value pair using the key. If there is no entry
|
|
% for the given key, returns the pair for the next higher key instead.
|
|
% Aborts if there is no key with the given or higher value.
|
|
:- pred map__upper_bound_lookup(map(K, V)::in, K::in, K::out, V::out) is det.
|
|
|
|
% Search map for data.
|
|
:- pred map__inverse_search(map(K, V)::in, V::in, K::out) is nondet.
|
|
|
|
% Insert a new key and corresponding value into a map.
|
|
% Fail if the key already exists.
|
|
:- pred map__insert(map(K, V)::in, K::in, V::in, map(K, V)::out) is semidet.
|
|
:- func map__insert(map(K, V), K, V) = map(K, V) is semidet.
|
|
|
|
% Insert a new key and corresponding value into a map.
|
|
% Abort if the key already exists.
|
|
:- pred map__det_insert(map(K, V)::in, K::in, V::in, map(K, V)::out) is det.
|
|
:- func map__det_insert(map(K, V), K, V) = map(K, V).
|
|
|
|
% Apply map__det_insert to key - value pairs from corresponding lists.
|
|
:- pred map__det_insert_from_corresponding_lists(map(K, V)::in, list(K)::in,
|
|
list(V)::in, map(K, V)::out) is det.
|
|
|
|
:- func map__det_insert_from_corresponding_lists(map(K, V), list(K), list(V))
|
|
= map(K, V).
|
|
|
|
% Apply map__det_insert to key - value pairs from the assoc_lists.
|
|
:- pred map__det_insert_from_assoc_list(map(K, V)::in, assoc_list(K, V)::in,
|
|
map(K, V)::out) is det.
|
|
:- func map__det_insert_from_assoc_list(map(K, V), assoc_list(K, V))
|
|
= map(K, V).
|
|
|
|
% Apply map__set to key - value pairs from corresponding lists.
|
|
:- pred map__set_from_corresponding_lists(map(K, V)::in, list(K)::in,
|
|
list(V)::in, map(K, V)::out) is det.
|
|
:- func map__set_from_corresponding_lists(map(K, V), list(K), list(V))
|
|
= map(K, V).
|
|
|
|
:- pred map__set_from_assoc_list(map(K, V)::in, assoc_list(K, V)::in,
|
|
map(K, V)::out) is det.
|
|
:- func map__set_from_assoc_list(map(K, V), assoc_list(K, V)) = map(K, V).
|
|
|
|
% Update the value corresponding to a given key
|
|
% Fail if the key doesn't already exist.
|
|
:- pred map__update(map(K, V)::in, K::in, V::in, map(K, V)::out) is semidet.
|
|
:- func map__update(map(K, V), K, V) = map(K, V) is semidet.
|
|
|
|
% Update the value corresponding to a given key
|
|
% Abort if the key doesn't already exist.
|
|
:- pred map__det_update(map(K, V)::in, K::in, V::in, map(K, V)::out) is det.
|
|
:- func map__det_update(map(K, V), K, V) = map(K, V).
|
|
|
|
% Update value if the key is already present, otherwise
|
|
% insert new key and value.
|
|
:- pred map__set(map(K, V), K, V, map(K, V)).
|
|
:- mode map__set(di, di, di, uo) is det.
|
|
:- mode map__set(in, in, in, out) is det.
|
|
|
|
:- func map__set(map(K, V), K, V) = map(K, V).
|
|
|
|
% Given a map, return a list of all the keys in the map.
|
|
:- pred map__keys(map(K, _V)::in, list(K)::out) is det.
|
|
:- func map__keys(map(K, _V)) = list(K).
|
|
|
|
% Given a map, return a list of all the keys in the map,
|
|
% in sorted order.
|
|
:- pred map__sorted_keys(map(K, _V)::in, list(K)::out) is det.
|
|
:- func map__sorted_keys(map(K, _V)) = list(K).
|
|
|
|
% Given a map, return a list of all the data values in the map.
|
|
:- pred map__values(map(_K, V)::in, list(V)::out) is det.
|
|
:- func map__values(map(_K, V)) = list(V).
|
|
|
|
% Convert a map to an association list.
|
|
:- pred map__to_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.
|
|
:- func map__to_assoc_list(map(K, V)) = assoc_list(K, V).
|
|
|
|
% Convert a map to an association list which is sorted on the keys.
|
|
:- pred map__to_sorted_assoc_list(map(K, V)::in, assoc_list(K, V)::out) is det.
|
|
:- func map__to_sorted_assoc_list(map(K, V)) = assoc_list(K, V).
|
|
|
|
% Convert an association list to a map.
|
|
:- pred map__from_assoc_list(assoc_list(K, V)::in, map(K, V)::out) is det.
|
|
:- func map__from_assoc_list(assoc_list(K, V)) = map(K, V).
|
|
|
|
% Convert a sorted association list to a map.
|
|
:- pred map__from_sorted_assoc_list(assoc_list(K, V)::in, map(K, V)::out)
|
|
is det.
|
|
:- func map__from_sorted_assoc_list(assoc_list(K, V)) = map(K, V).
|
|
|
|
% Delete a key-value pair from a map.
|
|
% If the key is not present, leave the map unchanged.
|
|
:- pred map__delete(map(K, V), K, map(K, V)).
|
|
:- mode map__delete(di, in, uo) is det.
|
|
:- mode map__delete(in, in, out) is det.
|
|
|
|
:- func map__delete(map(K, V), K) = map(K, V).
|
|
|
|
% Apply map__delete/3 to a list of keys.
|
|
:- pred map__delete_list(map(K, V), list(K), map(K, V)).
|
|
:- mode map__delete_list(di, in, uo) is det.
|
|
:- mode map__delete_list(in, in, out) is det.
|
|
|
|
:- func map__delete_list(map(K, V), list(K)) = map(K, V).
|
|
|
|
% Delete a key-value pair from a map and return the value.
|
|
% Fail if the key is not present.
|
|
:- pred map__remove(map(K, V)::in, K::in, V::out, map(K, V)::out) is semidet.
|
|
|
|
% Delete a key-value pair from a map and return the value.
|
|
% Abort if the key is not present.
|
|
:- pred map__det_remove(map(K, V)::in, K::in, V::out, map(K, V)::out) is det.
|
|
|
|
% Count the number of elements in the map.
|
|
:- pred map__count(map(K, V)::in, int::out) is det.
|
|
:- func map__count(map(K, V)) = int.
|
|
|
|
% Convert a pair of lists (which must be of the same length)
|
|
% to a map.
|
|
:- pred map__from_corresponding_lists(list(K)::in, list(V)::in, map(K, V)::out)
|
|
is det.
|
|
:- func map__from_corresponding_lists(list(K), list(V)) = map(K, V).
|
|
|
|
% For map__merge(MapA, MapB, Map), MapA and MapB must
|
|
% not both contain the same key.
|
|
:- pred map__merge(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
:- func map__merge(map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% For map__overlay(MapA, MapB, Map), if MapA and MapB both
|
|
% contain the same key, then Map will map that key to
|
|
% the value from MapB. In otherwords, MapB takes precedence
|
|
% over MapA.
|
|
:- pred map__overlay(map(K, V)::in, map(K, V)::in, map(K, V)::out) is det.
|
|
:- func map__overlay(map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% map__select takes a map and a set of keys and returns
|
|
% a map containing the keys in the set and their corresponding
|
|
% values.
|
|
:- pred map__select(map(K, V)::in, set(K)::in, map(K, V)::out) is det.
|
|
:- func map__select(map(K, V), set(K)) = map(K, V).
|
|
|
|
% Given a list of keys, produce a list of their corresponding
|
|
% values in a specified map.
|
|
:- pred map__apply_to_list(list(K)::in, map(K, V)::in, list(V)::out) is det.
|
|
:- func map__apply_to_list(list(K), map(K, V)) = list(V).
|
|
|
|
% Declaratively, a NOP.
|
|
% Operationally, a suggestion that the implementation
|
|
% optimize the representation of the map in the expectation
|
|
% of a number of lookups but few or no modifications.
|
|
:- pred map__optimize(map(K, V)::in, map(K, V)::out) is det.
|
|
:- func map__optimize(map(K, V)) = map(K, V).
|
|
|
|
% Remove the smallest item from the map, fail if
|
|
% the map is empty.
|
|
:- pred map__remove_smallest(map(K, V)::in, K::out, V::out, map(K, V)::out)
|
|
is semidet.
|
|
|
|
% Perform an inorder traversal of the map, applying
|
|
% an accumulator predicate for each key-value pair.
|
|
:- pred map__foldl(pred(K, V, T, T), map(K, V), T, T).
|
|
:- mode map__foldl(pred(in, in, in, out) is det, in, in, out) is det.
|
|
:- mode map__foldl(pred(in, in, in, out) is semidet, in, in, out) is semidet.
|
|
:- mode map__foldl(pred(in, in, di, uo) is det, in, di, uo) is det.
|
|
|
|
:- func map__foldl(func(K, V, T) = T, map(K, V), T) = T.
|
|
|
|
% Perform an inorder traversal of the map, applying
|
|
% an accumulator predicate with two accumulators for
|
|
% each key-value pair.
|
|
% (Although no more expressive than map__foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
:- pred map__foldl2(pred(K, V, T, T, U, U), map(K, V), T, T, U, U).
|
|
:- mode map__foldl2(pred(in, in, in, out, in, out) is det,
|
|
in, in, out, in, out) is det.
|
|
:- mode map__foldl2(pred(in, in, in, out, in, out) is semidet,
|
|
in, in, out, in, out) is semidet.
|
|
:- mode map__foldl2(pred(in, in, in, out, di, uo) is det,
|
|
in, in, out, di, uo) is det.
|
|
:- mode map__foldl2(pred(in, in, di, uo, di, uo) is det,
|
|
in, di, uo, di, uo) is det.
|
|
|
|
% Perform an inorder traversal of the map, applying
|
|
% an accumulator predicate with three accumulators for
|
|
% each key-value pair.
|
|
% (Although no more expressive than map__foldl, this is often
|
|
% a more convenient format, and a little more efficient).
|
|
:- pred map__foldl3(pred(K, V, T, T, U, U, W, W), map(K, V), T, T, U, U, W, W).
|
|
:- mode map__foldl3(pred(in, in, in, out, in, out, in, out) is det,
|
|
in, in, out, in, out, in, out) is det.
|
|
:- mode map__foldl3(pred(in, in, in, out, in, out, in, out) is semidet,
|
|
in, in, out, in, out, in, out) is semidet.
|
|
:- mode map__foldl3(pred(in, in, in, out, in, out, di, uo) is det,
|
|
in, in, out, in, out, di, uo) is det.
|
|
:- mode map__foldl3(pred(in, in, in, out, di, uo, di, uo) is det,
|
|
in, in, out, di, uo, di, uo) is det.
|
|
:- mode map__foldl3(pred(in, in, di, uo, di, uo, di, uo) is det,
|
|
in, di, uo, di, uo, di, uo) is det.
|
|
|
|
% Apply a transformation predicate to all the values
|
|
% in a map.
|
|
:- pred map__map_values(pred(K, V, W), map(K, V), map(K, W)).
|
|
:- mode map__map_values(pred(in, in, out) is det, in, out) is det.
|
|
:- mode map__map_values(pred(in, in, out) is semidet, in, out) is semidet.
|
|
|
|
:- func map__map_values(func(K, V) = W, map(K, V)) = map(K, W).
|
|
|
|
% Apply a transformation predicate to all the values
|
|
% in a map, while continuously updating an accumulator.
|
|
:- pred map__map_foldl(pred(K, V, W, A, A), map(K, V), map(K, W), A, A).
|
|
:- mode map__map_foldl(pred(in, in, out, in, out) is det, in, out, in, out)
|
|
is det.
|
|
:- mode map__map_foldl(pred(in, in, out, in, out) is semidet, in, out, in, out)
|
|
is semidet.
|
|
|
|
% Given two maps M1 and M2, create a third map M3 that has only the
|
|
% keys that occur in both M1 and M2. For keys that occur in both M1
|
|
% and M2, compute the value in the final map by applying the supplied
|
|
% predicate to the values associated with the key in M1 and M2.
|
|
% Fail if and only if this predicate fails on the values associated
|
|
% with some common key.
|
|
:- pred map__intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode map__intersect(pred(in, in, out) is semidet, in, in, out) is semidet.
|
|
:- mode map__intersect(pred(in, in, out) is det, in, in, out) is det.
|
|
|
|
:- func map__intersect(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Calls map__intersect. Aborts if map__intersect fails.
|
|
:- pred map__det_intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode map__det_intersect(pred(in, in, out) is semidet, in, in, out) is det.
|
|
|
|
:- func map__det_intersect(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
:- mode map__det_intersect(func(in, in) = out is semidet, in, in) = out is det.
|
|
|
|
% Given two maps M1 and M2, create a third map M3 that has only the
|
|
% keys that occur in both M1 and M2. For keys that occur in both M1
|
|
% and M2, compute the corresponding values. If they are the same,
|
|
% include the key/value pair in M3. If they differ, do not include the
|
|
% key in M3.
|
|
%
|
|
% This predicate effectively considers the input maps to be sets of
|
|
% key/value pairs, computes the intersection of those two sets, and
|
|
% returns the map corresponding to the intersection.
|
|
%
|
|
% map__common_subset is very similar to map__intersect, but can succeed
|
|
% even with an output map that does not contain an entry for a key
|
|
% value that occurs in both input maps.
|
|
:- func map__common_subset(map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Given two maps M1 and M2, create a third map M3 that all the keys
|
|
% that occur in either M1 and M2. For keys that occur in both M1
|
|
% and M2, compute the value in the final map by applying the supplied
|
|
% predicate to the values associated with the key in M1 and M2.
|
|
% Fail if and only if this predicate fails on the values associated
|
|
% with some common key.
|
|
:- pred map__union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode map__union(pred(in, in, out) is semidet, in, in, out) is semidet.
|
|
:- mode map__union(pred(in, in, out) is det, in, in, out) is det.
|
|
|
|
:- func map__union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
|
|
% Calls map__union. Aborts if map__union fails.
|
|
:- pred map__det_union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
|
|
:- mode map__det_union(pred(in, in, out) is semidet, in, in, out) is det.
|
|
|
|
:- func map__det_union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
|
|
:- mode map__det_union(func(in, in) = out is semidet, in, in) = out is det.
|
|
|
|
% Field selection for maps.
|
|
|
|
% Map ^ elem(Key) = map__search(Map, Key).
|
|
:- func map__elem(K, map(K, V)) = V is semidet.
|
|
|
|
% Map ^ det_elem(Key) = map__lookup(Map, Key).
|
|
:- func map__det_elem(K, map(K, V)) = V.
|
|
|
|
% Field update for maps.
|
|
|
|
% (Map ^ elem(Key) := Value) = map__set(Map, Key, Value).
|
|
:- func 'map__elem :='(K, map(K, V), V) = map(K, V).
|
|
|
|
% (Map ^ det_elem(Key) := Value) = map__det_update(Map, Key, Value).
|
|
:- func 'map__det_elem :='(K, map(K, V), V) = map(K, V).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
% Everything below here is not intended to be part of the public interface,
|
|
% and will not be included in the Mercury library reference manual.
|
|
|
|
:- interface.
|
|
|
|
:- import_module tree234.
|
|
:- import_module term. % for var/1.
|
|
|
|
:- type map(K, V) == tree234(K, V).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pragma type_spec(map__search/3, K = var(_)).
|
|
:- pragma type_spec(map__search/3, K = int).
|
|
|
|
:- pragma type_spec(map__search/2, K = var(_)).
|
|
:- pragma type_spec(map__search/2, K = int).
|
|
|
|
:- pragma type_spec(map__lookup/3, K = var(_)).
|
|
:- pragma type_spec(map__lookup/3, K = int).
|
|
|
|
:- pragma type_spec(map__lookup/2, K = var(_)).
|
|
:- pragma type_spec(map__lookup/2, K = int).
|
|
|
|
:- pragma type_spec(map__set(in, in, in, out), K = var(_)).
|
|
:- pragma type_spec(map__set/3, K = var(_)).
|
|
|
|
:- pragma type_spec(map__det_update/4, K = var(_)).
|
|
:- pragma type_spec(map__det_update/4, K = int).
|
|
|
|
:- pragma type_spec(map__overlay/2, K = var(_)).
|
|
:- pragma type_spec(map__overlay/3, K = var(_)).
|
|
|
|
:- pragma type_spec(map__select/2, K = var(_)).
|
|
:- pragma type_spec(map__select/3, K = var(_)).
|
|
|
|
:- implementation.
|
|
:- import_module std_util, require, string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__init(M) :-
|
|
tree234__init(M).
|
|
|
|
map__is_empty(M) :-
|
|
tree234__is_empty(M).
|
|
|
|
map__contains(Map, K) :-
|
|
map__search(Map, K, _).
|
|
|
|
map__member(Map, K, V) :-
|
|
tree234__member(Map, K, V).
|
|
|
|
map__search(Map, K, V) :-
|
|
tree234__search(Map, K, V).
|
|
|
|
map__lookup(Map, K, V) :-
|
|
( tree234__search(Map, K, V1) ->
|
|
V = V1
|
|
;
|
|
report_lookup_error("map__lookup: key not found", K, V)
|
|
).
|
|
|
|
map__lower_bound_search(Map, SearchK, K, V) :-
|
|
tree234__lower_bound_search(Map, SearchK, K, V).
|
|
|
|
map__lower_bound_lookup(Map, SearchK, K, V) :-
|
|
( tree234__lower_bound_search(Map, SearchK, K1, V1) ->
|
|
K = K1,
|
|
V = V1
|
|
;
|
|
report_lookup_error("map__lower_bound_lookup: key not found",
|
|
SearchK, V)
|
|
).
|
|
|
|
map__upper_bound_search(Map, SearchK, K, V) :-
|
|
tree234__upper_bound_search(Map, SearchK, K, V).
|
|
|
|
map__upper_bound_lookup(Map, SearchK, K, V) :-
|
|
( tree234__upper_bound_search(Map, SearchK, K1, V1) ->
|
|
K = K1,
|
|
V = V1
|
|
;
|
|
report_lookup_error("map__upper_bound_lookup: key not found",
|
|
SearchK, V)
|
|
).
|
|
|
|
map__insert(Map0, K, V, Map) :-
|
|
tree234__insert(Map0, K, V, Map).
|
|
|
|
map__det_insert(Map0, K, V, Map) :-
|
|
( tree234__insert(Map0, K, V, Map1) ->
|
|
Map = Map1
|
|
;
|
|
report_lookup_error("map__det_insert: key already present",
|
|
K, V)
|
|
).
|
|
|
|
map__det_insert_from_corresponding_lists(Map0, Ks, Vs, Map) :-
|
|
(
|
|
Ks = [Key | Keys],
|
|
Vs = [Value | Values]
|
|
->
|
|
map__det_insert(Map0, Key, Value, Map1),
|
|
map__det_insert_from_corresponding_lists(Map1, Keys, Values,
|
|
Map)
|
|
;
|
|
Ks = [],
|
|
Vs = []
|
|
->
|
|
Map = Map0
|
|
;
|
|
error("map__det_insert_from_corresponding_lists - " ++
|
|
"lists do not correspond")
|
|
).
|
|
|
|
map__det_insert_from_assoc_list(Map, [], Map).
|
|
map__det_insert_from_assoc_list(Map0, [K - V | KVs], Map) :-
|
|
map__det_insert(Map0, K, V, Map1),
|
|
map__det_insert_from_assoc_list(Map1, KVs, Map).
|
|
|
|
map__set_from_corresponding_lists(Map0, Ks, Vs, Map) :-
|
|
(
|
|
Ks = [Key | Keys],
|
|
Vs = [Value | Values]
|
|
->
|
|
map__set(Map0, Key, Value, Map1),
|
|
map__set_from_corresponding_lists(Map1, Keys, Values, Map)
|
|
;
|
|
Ks = [],
|
|
Vs = []
|
|
->
|
|
Map = Map0
|
|
;
|
|
error("map__set_from_corresponding_lists - " ++
|
|
"lists do not correspond")
|
|
).
|
|
|
|
map__set_from_assoc_list(Map, [], Map).
|
|
map__set_from_assoc_list(Map0, [K - V | KVs], Map) :-
|
|
map__set(Map0, K, V, Map1),
|
|
map__set_from_assoc_list(Map1, KVs, Map).
|
|
|
|
map__update(Map0, K, V, Map) :-
|
|
tree234__update(Map0, K, V, Map).
|
|
|
|
map__det_update(Map0, K, V, Map) :-
|
|
( tree234__update(Map0, K, V, Map1) ->
|
|
Map = Map1
|
|
;
|
|
report_lookup_error("map__det_update: key not found", K, V)
|
|
).
|
|
|
|
map__set(Map0, K, V, Map) :-
|
|
tree234__set(Map0, K, V, Map).
|
|
|
|
map__keys(Map, KeyList) :-
|
|
tree234__keys(Map, KeyList).
|
|
|
|
map__sorted_keys(Map, KeyList) :-
|
|
% Guaranteed to yield sorted lists.
|
|
tree234__keys(Map, KeyList).
|
|
|
|
map__values(Map, KeyList) :-
|
|
tree234__values(Map, KeyList).
|
|
|
|
map__to_assoc_list(M, L) :-
|
|
tree234__tree234_to_assoc_list(M, L).
|
|
|
|
map__to_sorted_assoc_list(M, L) :-
|
|
% Guaranteed to yield sorted lists.
|
|
tree234__tree234_to_assoc_list(M, L).
|
|
|
|
map__from_assoc_list(L, M) :-
|
|
tree234__assoc_list_to_tree234(L, M).
|
|
|
|
map__from_sorted_assoc_list(L, M) :-
|
|
tree234__assoc_list_to_tree234(L, M).
|
|
|
|
map__delete(Map0, Key, Map) :-
|
|
tree234__delete(Map0, Key, Map).
|
|
|
|
map__delete_list(Map, [], Map).
|
|
map__delete_list(Map0, [Key | Keys], Map) :-
|
|
map__delete(Map0, Key, Map1),
|
|
map__delete_list(Map1, Keys, Map).
|
|
|
|
map__remove(Map0, Key, Value, Map) :-
|
|
tree234__remove(Map0, Key, Value, Map).
|
|
|
|
map__det_remove(Map0, Key, Value, Map) :-
|
|
( tree234__remove(Map0, Key, Value1, Map1) ->
|
|
Value = Value1,
|
|
Map = Map1
|
|
;
|
|
report_lookup_error("map__det_remove: key not found",
|
|
Key, Value)
|
|
).
|
|
|
|
map__count(Map, Count) :-
|
|
tree234__count(Map, Count).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__inverse_search(Map, V, K) :-
|
|
map__member(Map, K, V).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__from_corresponding_lists(Keys, Values, Map) :-
|
|
assoc_list__from_corresponding_lists(Keys, Values, AssocList),
|
|
tree234__assoc_list_to_tree234(AssocList, Map).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__merge(M0, M1, M) :-
|
|
map__to_assoc_list(M0, ML0),
|
|
map__to_assoc_list(M1, ML1),
|
|
list__merge(ML0, ML1, ML),
|
|
map__from_sorted_assoc_list(ML, M).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__optimize(Map, Map).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__overlay(Map0, Map1, Map) :-
|
|
map__to_assoc_list(Map1, AssocList),
|
|
map__overlay_2(AssocList, Map0, Map).
|
|
|
|
:- pred map__overlay_2(assoc_list(K, V)::in, map(K, V)::in, map(K, V)::out)
|
|
is det.
|
|
:- pragma type_spec(map__overlay_2/3, K = var(_)).
|
|
|
|
map__overlay_2([], Map, Map).
|
|
map__overlay_2([K - V | AssocList], Map0, Map) :-
|
|
map__set(Map0, K, V, Map1),
|
|
map__overlay_2(AssocList, Map1, Map).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__select(Original, KeySet, NewMap) :-
|
|
set__to_sorted_list(KeySet, KeyList),
|
|
map__init(NewMap0),
|
|
map__select_2(KeyList, Original, NewMap0, NewMap).
|
|
|
|
:- pred map__select_2(list(K)::in, map(K, V)::in, map(K, V)::in,
|
|
map(K, V)::out) is det.
|
|
:- pragma type_spec(map__select_2/4, K = var(_)).
|
|
|
|
map__select_2([], _Original, New, New).
|
|
map__select_2([K|Ks], Original, New0, New) :-
|
|
( map__search(Original, K, V) ->
|
|
map__set(New0, K, V, New1)
|
|
;
|
|
New1 = New0
|
|
),
|
|
map__select_2(Ks, Original, New1, New).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__apply_to_list([], _, []).
|
|
map__apply_to_list([K | Ks], Map, [V | Vs]) :-
|
|
map__lookup(Map, K, V),
|
|
map__apply_to_list(Ks, Map, Vs).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__remove_smallest(Map0, K, V, Map) :-
|
|
tree234__remove_smallest(Map0, K, V, Map).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__foldl(Pred, Map, !A) :-
|
|
tree234__foldl(Pred, Map, !A).
|
|
|
|
map__foldl2(Pred, Map, !A, !B) :-
|
|
tree234__foldl2(Pred, Map, !A, !B).
|
|
|
|
map__foldl3(Pred, Map, !A, !B, !C) :-
|
|
tree234__foldl3(Pred, Map, !A, !B, !C).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__map_values(Pred, Map0, Map) :-
|
|
tree234__map_values(Pred, Map0, Map).
|
|
|
|
map__map_foldl(Pred, Map0, Map, Acc0, Acc) :-
|
|
tree234__map_foldl(Pred, Map0, Map, Acc0, Acc).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__intersect(CommonPred, Map1, Map2, Common) :-
|
|
map__to_sorted_assoc_list(Map1, AssocList1),
|
|
map__to_sorted_assoc_list(Map2, AssocList2),
|
|
map__init(Common0),
|
|
map__intersect_2(AssocList1, AssocList2, CommonPred, Common0, Common).
|
|
|
|
:- pred map__intersect_2(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
|
|
map(K, V), map(K, V)).
|
|
:- mode map__intersect_2(in, in, pred(in, in, out) is semidet, in, out)
|
|
is semidet.
|
|
:- mode map__intersect_2(in, in, pred(in, in, out) is det, in, out)
|
|
is det.
|
|
|
|
map__intersect_2(AssocList1, AssocList2, CommonPred, Common0, Common) :-
|
|
(
|
|
AssocList1 = [],
|
|
AssocList2 = [],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [_ | _],
|
|
AssocList2 = [],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [],
|
|
AssocList2 = [_ | _],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [Key1 - Value1 | AssocTail1],
|
|
AssocList2 = [Key2 - Value2 | AssocTail2],
|
|
compare(R, Key1, Key2),
|
|
(
|
|
R = (=),
|
|
call(CommonPred, Value1, Value2, Value),
|
|
map__det_insert(Common0, Key1, Value, Common1),
|
|
map__intersect_2(AssocTail1, AssocTail2, CommonPred,
|
|
Common1, Common)
|
|
;
|
|
R = (<),
|
|
map__intersect_2(AssocTail1, AssocList2, CommonPred,
|
|
Common0, Common)
|
|
;
|
|
R = (>),
|
|
map__intersect_2(AssocList1, AssocTail2, CommonPred,
|
|
Common0, Common)
|
|
)
|
|
).
|
|
|
|
map__det_intersect(CommonPred, Map1, Map2, Common) :-
|
|
( map__intersect(CommonPred, Map1, Map2, CommonPrime) ->
|
|
Common = CommonPrime
|
|
;
|
|
error("map__det_intersect: map__intersect failed")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__common_subset(Map1, Map2) = Common :-
|
|
map__to_sorted_assoc_list(Map1, AssocList1),
|
|
map__to_sorted_assoc_list(Map2, AssocList2),
|
|
map__init(Common0),
|
|
map__common_subset_2(AssocList1, AssocList2, Common0) = Common.
|
|
|
|
:- func map__common_subset_2(assoc_list(K, V), assoc_list(K, V),
|
|
map(K, V)) = map(K, V).
|
|
|
|
map__common_subset_2(AssocList1, AssocList2, Common0) = Common :-
|
|
(
|
|
AssocList1 = [],
|
|
AssocList2 = [],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [_ | _],
|
|
AssocList2 = [],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [],
|
|
AssocList2 = [_ | _],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [Key1 - Value1 | AssocTail1],
|
|
AssocList2 = [Key2 - Value2 | AssocTail2],
|
|
compare(R, Key1, Key2),
|
|
(
|
|
R = (=),
|
|
( Value1 = Value2 ->
|
|
map__det_insert(Common0, Key1, Value1, Common1)
|
|
;
|
|
Common1 = Common0
|
|
),
|
|
Common = map__common_subset_2(AssocTail1, AssocTail2,
|
|
Common1)
|
|
;
|
|
R = (<),
|
|
Common = map__common_subset_2(AssocTail1, AssocList2,
|
|
Common0)
|
|
;
|
|
R = (>),
|
|
Common = map__common_subset_2(AssocList1, AssocTail2,
|
|
Common0)
|
|
)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
map__union(CommonPred, Map1, Map2, Common) :-
|
|
map__to_sorted_assoc_list(Map1, AssocList1),
|
|
map__to_sorted_assoc_list(Map2, AssocList2),
|
|
map__init(Common0),
|
|
map__union_2(AssocList1, AssocList2, CommonPred, Common0, Common).
|
|
|
|
:- pred map__union_2(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
|
|
map(K, V), map(K, V)).
|
|
:- mode map__union_2(in, in, pred(in, in, out) is semidet, in, out)
|
|
is semidet.
|
|
:- mode map__union_2(in, in, pred(in, in, out) is det, in, out)
|
|
is det.
|
|
|
|
map__union_2(AssocList1, AssocList2, CommonPred, Common0, Common) :-
|
|
(
|
|
AssocList1 = [],
|
|
AssocList2 = [],
|
|
Common = Common0
|
|
;
|
|
AssocList1 = [_ | _],
|
|
AssocList2 = [],
|
|
map__det_insert_from_assoc_list(Common0, AssocList1, Common)
|
|
;
|
|
AssocList1 = [],
|
|
AssocList2 = [_ | _],
|
|
map__det_insert_from_assoc_list(Common0, AssocList2, Common)
|
|
;
|
|
AssocList1 = [Key1 - Value1 | AssocTail1],
|
|
AssocList2 = [Key2 - Value2 | AssocTail2],
|
|
compare(R, Key1, Key2),
|
|
(
|
|
R = (=),
|
|
call(CommonPred, Value1, Value2, Value),
|
|
map__det_insert(Common0, Key1, Value, Common1),
|
|
map__union_2(AssocTail1, AssocTail2, CommonPred,
|
|
Common1, Common)
|
|
;
|
|
R = (<),
|
|
map__det_insert(Common0, Key1, Value1, Common1),
|
|
map__union_2(AssocTail1, AssocList2, CommonPred,
|
|
Common1, Common)
|
|
;
|
|
R = (>),
|
|
map__det_insert(Common0, Key2, Value2, Common1),
|
|
map__union_2(AssocList1, AssocTail2, CommonPred,
|
|
Common1, Common)
|
|
)
|
|
).
|
|
|
|
map__det_union(CommonPred, Map1, Map2, Union) :-
|
|
( map__union(CommonPred, Map1, Map2, UnionPrime) ->
|
|
Union = UnionPrime
|
|
;
|
|
error("map__det_union: map__union failed")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
% Ralph Becket <rwab1@cl.cam.ac.uk> 27/04/99
|
|
% Functional forms added.
|
|
|
|
map__init = M :-
|
|
map__init(M).
|
|
|
|
map__search(M, K) = V :-
|
|
map__search(M, K, V).
|
|
|
|
map__lookup(M, K) = V :-
|
|
map__lookup(M, K, V).
|
|
|
|
map__insert(M1, K, V) = M2 :-
|
|
map__insert(M1, K, V, M2).
|
|
|
|
map__det_insert(M1, K, V) = M2 :-
|
|
map__det_insert(M1, K, V, M2).
|
|
|
|
map__det_insert_from_corresponding_lists(M1, Ks, Vs) = M2 :-
|
|
map__det_insert_from_corresponding_lists(M1, Ks, Vs, M2).
|
|
|
|
map__det_insert_from_assoc_list(M1, AL) = M2 :-
|
|
map__det_insert_from_assoc_list(M1, AL, M2).
|
|
|
|
map__set_from_corresponding_lists(M1, Ks, Vs) = M2 :-
|
|
map__set_from_corresponding_lists(M1, Ks, Vs, M2).
|
|
|
|
map__set_from_assoc_list(M1, AL) = M2 :-
|
|
map__set_from_assoc_list(M1, AL, M2).
|
|
|
|
map__update(M1, K, V) = M2 :-
|
|
map__update(M1, K, V, M2).
|
|
|
|
map__det_update(M1, K, V) = M2 :-
|
|
map__det_update(M1, K, V, M2).
|
|
|
|
map__set(M1, K, V) = M2 :-
|
|
map__set(M1, K, V, M2).
|
|
|
|
map__keys(M) = Ks :-
|
|
map__keys(M, Ks).
|
|
|
|
map__sorted_keys(M) = Ks :-
|
|
map__sorted_keys(M, Ks).
|
|
|
|
map__values(M) = Vs :-
|
|
map__values(M, Vs).
|
|
|
|
map__to_assoc_list(M) = AL :-
|
|
map__to_assoc_list(M, AL).
|
|
|
|
map__to_sorted_assoc_list(M) = AL :-
|
|
map__to_sorted_assoc_list(M, AL).
|
|
|
|
map__from_assoc_list(AL) = M :-
|
|
map__from_assoc_list(AL, M).
|
|
|
|
map__from_sorted_assoc_list(AL) = M :-
|
|
map__from_sorted_assoc_list(AL, M).
|
|
|
|
map__delete(M1, K) = M2 :-
|
|
map__delete(M1, K, M2).
|
|
|
|
map__delete_list(M1, Ks) = M2 :-
|
|
map__delete_list(M1, Ks, M2).
|
|
|
|
map__count(M) = N :-
|
|
map__count(M, N).
|
|
|
|
map__from_corresponding_lists(Ks, Vs) = M :-
|
|
map__from_corresponding_lists(Ks, Vs, M).
|
|
|
|
map__merge(M1, M2) = M3 :-
|
|
map__merge(M1, M2, M3).
|
|
|
|
map__overlay(M1, M2) = M3 :-
|
|
map__overlay(M1, M2, M3).
|
|
|
|
map__select(M1, S) = M2 :-
|
|
map__select(M1, S, M2).
|
|
|
|
map__apply_to_list(Ks, M) = Vs :-
|
|
map__apply_to_list(Ks, M, Vs).
|
|
|
|
map__optimize(M1) = M2 :-
|
|
map__optimize(M1, M2).
|
|
|
|
map__foldl(F, M, A) = B :-
|
|
P = ( pred(W::in, X::in, Y::in, Z::out) is det :- Z = F(W, X, Y) ),
|
|
map__foldl(P, M, A, B).
|
|
|
|
map__map_values(F, M1) = M2 :-
|
|
P = ( pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map__map_values(P, M1, M2).
|
|
|
|
map__intersect(F, M1, M2) = M3 :-
|
|
P = ( pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map__intersect(P, M1, M2, M3).
|
|
|
|
map__det_intersect(PF, M1, M2) = M3 :-
|
|
P = ( pred(X::in, Y::in, Z::out) is semidet :- Z = PF(X, Y) ),
|
|
map__det_intersect(P, M1, M2, M3).
|
|
|
|
map__union(F, M1, M2) = M3 :-
|
|
P = ( pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
|
|
map__union(P, M1, M2, M3).
|
|
|
|
map__det_union(F, M1, M2) = M3 :-
|
|
P = ( pred(X::in, Y::in, Z::out) is semidet :- Z = F(X, Y) ),
|
|
map__det_union(P, M1, M2, M3).
|
|
|
|
map__elem(Key, Map) = map__search(Map, Key).
|
|
|
|
map__det_elem(Key, Map) = map__lookup(Map, Key).
|
|
|
|
'map__elem :='(Key, Map, Value) = map__set(Map, Key, Value).
|
|
|
|
'map__det_elem :='(Key, Map, Value) = map__det_update(Map, Key, Value).
|