The Mercury Library Reference Manual

This file documents the Mercury standard library, version rotd-2004-05-11.

Copyright (C) 1995-1997,1999-2004 The University of Melbourne.

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.

Table of Contents


Node:Top, Up:(mercury)

Mercury Library Reference Manual, version rotd-2004-05-11

The Mercury standard library contains a variety of modules which we hope may be of general usefulness. If you write a module that would be useful to others, and you would like us to include it as part of the Mercury standard library, please let us know.

The following documentation is simply the interface parts to those modules, automatically extracted from the source code. Some of the library modules are not very well documented; we apologize.

For many of the modules in the standard library, we have not yet had enough experience using them to be confident that the current interface is satisfactory; it is likely that the interfaces to many of the modules in the standard library will change somewhat in future releases of the Mercury system. Some modules are rather experimental modules that may even be removed in future releases. Of course, we wouldn't make changes gratuitously, but at the current time, preserving 100% backwards compatibility would be disadvantageous in the long run.

To help you protect yourself from depending on modules that are likely to change, each module has a comment "stability: low/medium/high" at the top which gives an indication of the likely stability of the interface to that module. For modules whose stability is "high", new functionality may be added to the interface, but we envisage very few if any changes to the interface of the sort that might break existing code. For modules whose stability is "medium", we expect that changes are more likely. For modules whose stability is "low", such changes are highly likely. If you want to minimize the possibility of your programs requiring modification to work with new releases of the Mercury system, we recommend that if possible you use only those modules whose stability is described as either "medium to high" or "high".


Node:array, Next:, Previous:Top, Up:Top

1 array


%--------------------------------------------------%
% Copyright (C) 1993-1995, 1997-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: array.m
% Main authors: fjh, bromage
% Stability: medium-low

% This module provides dynamically-sized one-dimensional arrays.
% Array indices start at zero.

% By default, the array__set and array__lookup procedures will check
% for bounds errors.  But for better performance, it is possible to
% disable some of the checking by compiling with `--intermodule-optimization'
% and with the C macro symbol `ML_OMIT_ARRAY_BOUNDS_CHECKS'
% defined, e.g. by using `MCFLAGS=--intermodule-optimization' and
% `CFLAGS=-DML_OMIT_ARRAY_BOUNDS_CHECKS' in your Mmakefile,
% or by compiling with the command
% `mmc --intermodule-optimization --cflags -DML_OMIT_ARRAY_BOUNDS_CHECKS'.
%
% For maximum performance, all bounds checking can be disabled by
% recompiling this module using `CFLAGS=-DML_OMIT_ARRAY_BOUNDS_CHECKS'
% or `mmc --cflags -DML_OMIT_ARRAY_BOUNDS_CHECKS' as above. You can
% either recompile the entire library, or just copy `array.m' to your
% application's source directory and link with it directly instead of as
% part of the library.
%

% WARNING!
%
% Arrays are currently not unique objects - until this situation is
% resolved it is up to the programmer to ensure that arrays are used
% in such a way as to preserve correctness.  In the absence of mode
% reordering, one should therefore assume that evaluation will take
% place in left-to-right order.  For example, the following code will
% probably not work as expected (f is a function, A an array, I an
% index, and X an appropriate value):
%
%       Y = f(A ^ elem(I) := X, A ^ elem(I))
%
% The compiler is likely to compile this as
%
%       V0 = A ^ elem(I) := X,
%       V1 = A ^ elem(I),
%       Y  = f(V0, V1)
%
% and will be unaware that the first line should be ordered
% *after* the second.  The safest thing to do is write things out
% by hand in the form
%
%       A0I = A0 ^ elem(I),
%       A1  = A0 ^ elem(I) := X,
%       Y   = f(A1, A0I)

%--------------------------------------------------%
%--------------------------------------------------%

:- module array.
:- interface.
:- import_module list, std_util, random.

:- type array(T).

:- inst array(I) = bound(array(I)).
:- inst array == array(ground).
:- inst array_skel == array(free).

	% XXX the current Mercury compiler doesn't support `ui' modes,
	% so to work-around that problem, we currently don't use
	% unique modes in this module.

% :- inst uniq_array(I) = unique(array(I)).
% :- inst uniq_array == uniq_array(unique).
:- inst uniq_array(I) = bound(array(I)). % XXX work-around
:- inst uniq_array == uniq_array(ground). % XXX work-around
:- inst uniq_array_skel == uniq_array(free).

:- mode array_di == di(uniq_array).
:- mode array_uo == out(uniq_array).
:- mode array_ui == in(uniq_array).

% :- inst mostly_uniq_array(I) = mostly_unique(array(I)).
% :- inst mostly_uniq_array == mostly_uniq_array(mostly_unique).
:- inst mostly_uniq_array(I) = bound(array(I)).	% XXX work-around
:- inst mostly_uniq_array == mostly_uniq_array(ground).	% XXX work-around
:- inst mostly_uniq_array_skel == mostly_uniq_array(free).

:- mode array_mdi == mdi(mostly_uniq_array).
:- mode array_muo == out(mostly_uniq_array).
:- mode array_mui == in(mostly_uniq_array).

	% An `array__index_out_of_bounds' is the exception thrown
	% on out-of-bounds array accesses. The string describes
	% the predicate or function reporting the error.
:- type array__index_out_of_bounds
	---> array__index_out_of_bounds(string).

%--------------------------------------------------%

	% array__make_empty_array(Array) creates an array of size zero
	% starting at lower bound 0.
:- pred array__make_empty_array(array(T)::array_uo) is det.

:- func array__make_empty_array = (array(T)::array_uo) is det.

	% array__init(Size, Init, Array) creates an array
	% with bounds from 0 to Size-1, with each element initialized to Init.
:- pred array__init(int, T, array(T)).
:- mode array__init(in, in, array_uo) is det.

:- func array__init(int, T) = array(T).
:- mode array__init(in, in) = array_uo is det.

	% array/1 is a function that constructs an array from a list.
	% (It does the same thing as the predicate array__from_list/2.)
	% The syntax `array([...])' is used to represent arrays
	% for io__read, io__write, term_to_type, and type_to_term.
:- func array(list(T)) = array(T).
:- mode array(in) = array_uo is det.

%--------------------------------------------------%

	% array__min returns the lower bound of the array.
	% Note: in this implementation, the lower bound is always zero.
:- pred array__min(array(_T), int).
:- mode array__min(array_ui, out) is det.
:- mode array__min(in, out) is det.

:- func array__min(array(_T)) = int.
:- mode array__min(array_ui) = out is det.
:- mode array__min(in) = out is det.

	% array__max returns the upper bound of the array.
:- pred array__max(array(_T), int).
:- mode array__max(array_ui, out) is det.
:- mode array__max(in, out) is det.

:- func array__max(array(_T)) = int.
:- mode array__max(array_ui) = out is det.
:- mode array__max(in) = out is det.

	% array__size returns the length of the array,
	% i.e. upper bound - lower bound + 1.
:- pred array__size(array(_T), int).
:- mode array__size(array_ui, out) is det.
:- mode array__size(in, out) is det.

:- func array__size(array(_T)) = int.
:- mode array__size(array_ui) = out is det.
:- mode array__size(in) = out is det.

	% array__bounds returns the upper and lower bounds of an array.
	% Note: in this implementation, the lower bound is always zero.
:- pred array__bounds(array(_T), int, int).
:- mode array__bounds(array_ui, out, out) is det.
:- mode array__bounds(in, out, out) is det.

	% array__in_bounds checks whether an index is in the bounds
	% of an array.
:- pred array__in_bounds(array(_T), int).
:- mode array__in_bounds(array_ui, in) is semidet.
:- mode array__in_bounds(in, in) is semidet.

%--------------------------------------------------%

	% array__lookup returns the Nth element of an array.
	% Throws an exception if the index is out of bounds.
:- pred array__lookup(array(T), int, T).
:- mode array__lookup(array_ui, in, out) is det.
:- mode array__lookup(in, in, out) is det.

:- func array__lookup(array(T), int) = T.
:- mode array__lookup(array_ui, in) = out is det.
:- mode array__lookup(in, in) = out is det.

	% array__semidet_lookup returns the Nth element of an array.
	% It fails if the index is out of bounds.
:- pred array__semidet_lookup(array(T), int, T).
:- mode array__semidet_lookup(array_ui, in, out) is semidet.
:- mode array__semidet_lookup(in, in, out) is semidet.

	% array__set sets the nth element of an array, and returns the
	% resulting array (good opportunity for destructive update ;-).
	% Throws an exception if the index is out of bounds.
:- pred array__set(array(T), int, T, array(T)).
:- mode array__set(array_di, in, in, array_uo) is det.

:- func array__set(array(T), int, T) = array(T).
:- mode array__set(array_di, in, in) = array_uo is det.

	% array__semidet_set sets the nth element of an array,
	% and returns the resulting array.
	% It fails if the index is out of bounds.
:- pred array__semidet_set(array(T), int, T, array(T)).
:- mode array__semidet_set(array_di, in, in, array_uo) is semidet.

	% array__slow_set sets the nth element of an array,
	% and returns the resulting array.  The initial array is not
	% required to be unique, so the implementation may not be able to use
	% destructive update.
	% It is an error if the index is out of bounds.
:- pred array__slow_set(array(T), int, T, array(T)).
:- mode array__slow_set(array_ui, in, in, array_uo) is det.
:- mode array__slow_set(in, in, in, array_uo) is det.

:- func array__slow_set(array(T), int, T) = array(T).
:- mode array__slow_set(array_ui, in, in) = array_uo is det.
:- mode array__slow_set(in, in, in) = array_uo is det.

	% array__semidet_slow_set sets the nth element of an array,
	% and returns the resulting array.  The initial array is not
	% required to be unique, so the implementation may not be able to use
	% destructive update.
	% It fails if the index is out of bounds.
:- pred array__semidet_slow_set(array(T), int, T, array(T)).
:- mode array__semidet_slow_set(array_ui, in, in, array_uo) is semidet.
:- mode array__semidet_slow_set(in, in, in, array_uo) is semidet.

	% Field selection for arrays.
	% Array ^ elem(Index) = array__lookup(Array, Index).
:- func array__elem(int, array(T)) = T.
:- mode array__elem(in, array_ui) = out is det.
:- mode array__elem(in, in) = out is det.

	% Field update for arrays.
	% (Array ^ elem(Index) := Value) = array__set(Array, Index, Value).
:- func 'array__elem :='(int, array(T), T) = array(T).
:- mode 'array__elem :='(in, array_di, in) = array_uo is det.

%--------------------------------------------------%

	% array__copy(Array0, Array):
	% Makes a new unique copy of an array.
:- pred array__copy(array(T), array(T)).
:- mode array__copy(array_ui, array_uo) is det.
:- mode array__copy(in, array_uo) is det.

:- func array__copy(array(T)) = array(T).
:- mode array__copy(array_ui) = array_uo is det.
:- mode array__copy(in) = array_uo is det.

	% array__resize(Array0, Size, Init, Array):
	% The array is expanded or shrunk to make it fit
	% the new size `Size'.  Any new entries are filled
	% with `Init'.
:- pred array__resize(array(T), int, T, array(T)).
:- mode array__resize(array_di, in, in, array_uo) is det.

:- func array__resize(array(T), int, T) = array(T).
:- mode array__resize(array_di, in, in) = array_uo is det.

	% array__shrink(Array0, Size, Array):
	% The array is shrunk to make it fit the new size `Size'.
	% Throws an exception if `Size' is larger than the size of `Array0'.
:- pred array__shrink(array(T), int, array(T)).
:- mode array__shrink(array_di, in, array_uo) is det.

:- func array__shrink(array(T), int) = array(T).
:- mode array__shrink(array_di, in) = array_uo is det.

	% array__from_list takes a list,
	% and returns an array containing those elements in
	% the same order that they occurred in the list.
:- pred array__from_list(list(T), array(T)).
:- mode array__from_list(in, array_uo) is det.

:- func array__from_list(list(T)) = array(T).
:- mode array__from_list(in) = array_uo is det.

	% array__to_list takes an array and returns a list containing
	% the elements of the array in the same order that they
	% occurred in the array.
:- pred array__to_list(array(T), list(T)).
:- mode array__to_list(array_ui, out) is det.
:- mode array__to_list(in, out) is det.

:- func array__to_list(array(T)) = list(T).
:- mode array__to_list(array_ui) = out is det.
:- mode array__to_list(in) = out is det.

	% array__fetch_items takes an array and a lower and upper
	% index, and places those items in the array between these
	% indices into a list.  It is an error if either index is
	% out of bounds.
:- pred array__fetch_items(array(T), int, int, list(T)).
:- mode array__fetch_items(in, in, in, out) is det.

:- func array__fetch_items(array(T), int, int) = list(T).
:- mode array__fetch_items(array_ui, in, in) = out is det.
:- mode array__fetch_items(in, in, in) = out is det.

	% array__bsearch takes an array, an element to be matched
	% and a comparison predicate and returns the position of
	% the first occurrence in the array of an element which is
	% equivalent to the given one in the ordering provided.
	% Assumes the array is sorted according to this ordering.
	% Fails if the element is not present.
:- pred array__bsearch(array(T), T, comparison_pred(T), maybe(int)).
:- mode array__bsearch(array_ui, in, in(comparison_pred), out) is det.
:- mode array__bsearch(in, in, in(comparison_pred), out) is det.

:- func array__bsearch(array(T), T, comparison_func(T)) = maybe(int).
:- mode array__bsearch(array_ui, in, in(comparison_func)) = out is det.
:- mode array__bsearch(in, in, in(comparison_func)) = out is det.

	% array__map(Closure, OldArray, NewArray) applys `Closure' to
	% each of the elements of `OldArray' to create `NewArray'.
:- pred array__map(pred(T1, T2), array(T1), array(T2)).
:- mode array__map(pred(in, out) is det, array_di, array_uo) is det.

:- func array__map(func(T1) = T2, array(T1)) = array(T2).
:- mode array__map(func(in) = out is det, array_di) = array_uo is det.

:- func array_compare(array(T), array(T)) = comparison_result.
:- mode array_compare(in, in) = uo is det.

	% array__sort(Array) returns a version of Array sorted
	% into ascending order.
	%
	% This sort is not stable.  That is, elements that
	% compare/3 decides are equal will appear together in
	% the sorted array, but not necessarily in the same
	% order in which they occurred in the input array.
	% This is primarily only an issue with types with
	% user-defined equivalence for which `equivalent'
	% objects are otherwise distinguishable.
	%
:- func array__sort(array(T)) = array(T).
:- mode array__sort(array_di) = array_uo is det.

	% array__foldl(Fn, Array, X) is equivalent to
	% 	list__foldl(Fn, array__to_list(Array), X)
	% but more efficient.
	%
:- func array__foldl(func(T1, T2) = T2, array(T1), T2) = T2.
:- mode array__foldl(func(in, in) = out is det, array_ui, in) = out is det.
:- mode array__foldl(func(in, in) = out is det, in, in) = out is det.
:- mode array__foldl(func(in, di) = uo is det, array_ui, di) = uo is det.
:- mode array__foldl(func(in, di) = uo is det, in, di) = uo is det.

	% array__foldr(Fn, Array, X) is equivalent to
	% 	list__foldr(Fn, array__to_list(Array), X)
	% but more efficient.
	%
:- func array__foldr(func(T1, T2) = T2, array(T1), T2) = T2.
:- mode array__foldr(func(in, in) = out is det, array_ui, in) = out is det.
:- mode array__foldr(func(in, in) = out is det, in, in) = out is det.
:- mode array__foldr(func(in, di) = uo is det, array_ui, di) = uo is det.
:- mode array__foldr(func(in, di) = uo is det, in, di) = uo is det.

	% array__random_permutation(A0, A, RS0, RS) permutes the elements in
	% A0 given random seed RS0 and returns the permuted array in A
	% and the next random seed in RS.
	%
:- pred array__random_permutation(array(T), array(T),
		random__supply, random__supply).
:- mode array__random_permutation(array_di, array_uo, mdi, muo) is det.

%--------------------------------------------------%


Node:array2d, Next:, Previous:array, Up:Top

2 array2d


%--------------------------------------------------%
% array2d.m
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%--------------------------------------------------%
% Copyright (C) 2003 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.
%--------------------------------------------------%
% Ralph Becket <rafe@cs.mu.oz.au>
% Wed Jan 15 15:17:11 EST 2003
%
% Two-dimensional rectangular (i.e. not ragged) array ADT.
%
% XXX The same caveats re: uniqueness of arrays apply to array2ds.
%
%--------------------------------------------------%

:- module array2d.

:- interface.

:- import_module int, array, list.



    % A array2d is a two-dimensional array stored in row-major order
    % (that is, the elements of the first row in left-to-right
    % order, followed by the elements of the second row and so forth.)
    %
:- type array2d(T).

:- inst array2d ---> array2d(ground, ground, array).

    % XXX These are work-arounds until we get nested uniqueness working.
    %
:- mode array2d_di == di(array2d).
:- mode array2d_ui == in(array2d).
:- mode array2d_uo == out(array2d).




    % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a array2d
    % of size M * N, with the special case that bounds(array2d([]), 0, 0).
    %
    % An exception is thrown if the sublists are not all the same length.
    %
:- func array2d(list(list(T))) = array2d(T).
:- mode array2d(in           ) = array2d_uo is det.

    % new(M, N, X) = array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]])
    % where each XIJ = X.  An exception is thrown if M < 0 or N < 0.
    %
:- func new(int, int, T ) = array2d(T).
:- mode new(in,  in,  in) = array2d_uo is det.

    % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = X
    % where X is the J+1th element of the I+1th row (that is, indices
    % start from zero.)
    %
    % An exception is thrown unless 0 =< I < M, 0 =< J < N.
    %
:- func array2d(T) ^ elem(int, int) = T.
:- mode array2d_ui ^ elem(in,  in ) = out is det.
:- mode in       ^ elem(in,  in ) = out is det.

    % T ^ unsafe_elem(I, J) is the same as T ^ elem(I, J) except that
    % behaviour is undefined if not in_bounds(T, I, J).
    %
:- func array2d(T) ^ unsafe_elem(int, int) = T.
:- mode array2d_ui ^ unsafe_elem(in,  in ) = out is det.
:- mode in       ^ unsafe_elem(in,  in ) = out is det.

    % ( T0 ^ elem(I, J) := X ) = T
    % where T ^ elem(II, JJ) = X                 if I = II, J = JJ
    % and   T ^ elem(II, JJ) = T0 ^ elem(II, JJ) otherwise.
    %
    % An exception is thrown unless 0 =< I < M, 0 =< J < N.
    %
:- func ( array2d(T) ^ elem(int, int) := T  ) = array2d(T).
:- mode ( array2d_di ^ elem(in,  in)  := in ) = array2d_uo is det.

    % T ^ unsafe_elem(I, J) := X is the same as T ^ elem(I, J) := X except
    % that behaviour is undefined if not in_bounds(T, I, J).
    %
:- func ( array2d(T) ^ unsafe_elem(int, int) := T  ) = array2d(T).
:- mode ( array2d_di ^ unsafe_elem(in,  in)  := in ) = array2d_uo is det.

    % bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), M, N)
    %
:- pred bounds(array2d(T), int, int).
:- mode bounds(array2d_ui, out, out) is det.
:- mode bounds(in,       out, out) is det.

    % in_bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), I, J)
    % succeeds iff 0 =< I < M, 0 =< J < N.
    %
:- pred in_bounds(array2d(T), int, int).
:- mode in_bounds(array2d_ui, in,  in ) is semidet.
:- mode in_bounds(in,       in,  in ) is semidet.

    % lists(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN])) =
    %     [[X11, ..., X1N], ..., [XM1, ..., XMN]]
    %
:- func lists(array2d(T)) = list(list(T)).
:- mode lists(array2d_ui) = out is det.
:- mode lists(in      ) = out is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:assoc_list, Next:, Previous:array2d, Up:Top

3 assoc_list


%--------------------------------------------------%
% Copyright (C) 1995-1997, 1999-2001, 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: assoc_list.m.
% Main authors: fjh, zs.
% Stability: medium to high.

% This file contains the definition of the type assoc_list(K, V)
% and some predicates which operate on those types.

%--------------------------------------------------%
%--------------------------------------------------%

:- module assoc_list.

:- interface.

:- import_module list, std_util.

%--------------------------------------------------%

:- type assoc_list(K,V)	==	list(pair(K,V)).

:- type assoc_list(T)	==	list(pair(T,T)).

	% Swap the two sides of the pairs in each member of the list.

:- pred assoc_list__reverse_members(assoc_list(K, V)::in,
	assoc_list(V, K)::out) is det.
:- func assoc_list__reverse_members(assoc_list(K, V)) = assoc_list(V, K).

	% Zip together two lists; abort if they are of different lengths.

:- pred assoc_list__from_corresponding_lists(list(K)::in, list(V)::in,
	assoc_list(K,V)::out) is det.
:- func assoc_list__from_corresponding_lists(list(K), list(V))
	= assoc_list(K,V).

	% Return the first member of each pair.

:- pred assoc_list__keys(assoc_list(K, V)::in, list(K)::out) is det.
:- func assoc_list__keys(assoc_list(K, V)) = list(K).

	% Return the second member of each pair.

:- pred assoc_list__values(assoc_list(K, V)::in, list(V)::out) is det.
:- func assoc_list__values(assoc_list(K, V)) = list(V).

	% Return the two lists contain respectively the first and second member
	% of each pair in the assoc_list.

:- pred assoc_list__keys_and_values(assoc_list(K, V)::in,
	list(K)::out, list(V)::out) is det.

	% Find the first element of the association list that matches
	% the given key, and return the associated value.

:- pred assoc_list__search(assoc_list(K, V)::in, K::in, V::out) is semidet.

	% Find the first element of the association list that matches
	% the given key. Return the associated value, and the original
	% list with the selected element removed.

:- pred assoc_list__remove(assoc_list(K, V)::in, K::in, V::out,
	assoc_list(K, V)::out) is semidet.

:- func assoc_list__map_values(func(K, V) = W, assoc_list(K, V))
	= assoc_list(K, W).

%--------------------------------------------------%


Node:bag, Next:, Previous:assoc_list, Up:Top

4 bag


%--------------------------------------------------%
% Copyright (C) 1994-1999, 2003-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: bag.m
%	An implementation of multisets.
% main author: conway, crs.
% stability: medium
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module bag.

:- interface.

:- import_module list, assoc_list.

:- type bag(T).

	% Create an empty bag.
	%
:- pred bag__init(bag(T)::out) is det.
:- func bag__init = bag(T).

	% Insert a particular value in a bag.
	%
:- pred bag__insert(bag(T)::in, T::in, bag(T)::out) is det.
:- func bag__insert(bag(T), T) = bag(T).

	% Insert a list of values into a bag.
	%
:- pred bag__insert_list(bag(T)::in, list(T)::in, bag(T)::out) is det.
:- func bag__insert_list(bag(T), list(T)) = bag(T).

	% Make a bag from a list.
	%
:- pred bag__from_list(list(T)::in, bag(T)::out) is det.
:- func bag__from_list(list(T)) = bag(T).

	% Given a bag, produce a sorted list containing all the values in
	% the bag.  Each value will appear in the list the same number of
	% times that it appears in the bag.
	%
:- pred bag__to_list(bag(T)::in, list(T)::out) is det.
:- func bag__to_list(bag(T)) = list(T).

	% Given a bag, produce a sorted list containing all the values in
	% the bag.  Each value will appear in the list once, with the
	% associated integer giving the number of times that it appears
	% in the bag.
	%
:- pred bag__to_assoc_list(bag(T)::in, assoc_list(T, int)::out) is det.
:- func bag__to_assoc_list(bag(T)) = assoc_list(T, int).

	% Given a bag, produce a sorted list with no duplicates
	% containing all the values in the bag.
	%
:- pred bag__to_list_without_duplicates(bag(T)::in, list(T)::out) is det.
:- func bag__to_list_without_duplicates(bag(T)) = list(T).

	% Remove one occurrence of a particular value from a bag.
	% Fail if the item does not exist in the bag.
	%
:- pred bag__remove(bag(T)::in, T::in, bag(T)::out) is semidet.

	% Remove one occurrence of a particular value from a bag.
	% Abort if the item does not exist in the bag.
	%
:- pred bag__det_remove(bag(T)::in, T::in, bag(T)::out) is det.
:- func bag__det_remove(bag(T), T) = bag(T).

	% Remove a list of values from a bag.  Duplicates are removed
	% from the bag the appropriate number of times.  Fail if any
	% of the items in the list do not exist in the bag.
	%
	% This call is logically equivalent to:
	%
	%	bag__remove_list(Bag0, RemoveList, Bag) :-
	%		bag__from_list(RemoveList, RemoveBag),
	%		bag__is_subbag(RemoveBag, Bag0),
	%		bag__subtract(Bag0, RemoveBag, Bag).
	%
:- pred bag__remove_list(bag(T)::in, list(T)::in, bag(T)::out) is semidet.

:- func bag__det_remove_list(bag(T), list(T)) = bag(T).

	% Remove a list of values from a bag.  Duplicates are removed
	% from the bag the appropriate number of times.  Abort if any
	% of the items in the list do not exist in the bag.
	%
:- pred bag__det_remove_list(bag(T)::in, list(T)::in, bag(T)::out) is det.

	% Delete one occurrence of a particular value from a bag.
	% If the key is not present, leave the bag unchanged.
	%
:- pred bag__delete(bag(T)::in, T::in, bag(T)::out) is det.
:- func bag__delete(bag(T), T) = bag(T).

	% Remove all occurrences of a particular value from a bag.
	% Fail if the item does not exist in the bag.
	%
:- pred bag__remove_all(bag(T)::in, T::in, bag(T)::out) is semidet.

:- func bag__delete_all(bag(T), T) = bag(T).

	% Delete all occurrences of a particular value from a bag.
	%
:- pred bag__delete_all(bag(T)::in, T::in, bag(T)::out) is det.

	% Check whether a bag contains a particular value.
	%
:- pred bag__contains(bag(T)::in, T::in) is semidet.

	% Count how many occurrences of the value the bag contains.
	%
:- pred bag__count_value(bag(T)::in, T::in, int::out) is det.
:- func bag__count_value(bag(T), T) = int.

	% bag__subtract(Bag0, SubBag, Bag)
	% subtracts SubBag from Bag0 to produce Bag
	% each element in SubBag is removed from Bag0 to produce Bag.
	% If an element exists in SubBag, but not in Bag, then that
	% element is not removed.
	% e.g. bag__subtract({1, 1, 2, 2, 3 }, {1, 1, 2, 3, 3, 3}, {2}).
	%
:- pred bag__subtract(bag(T)::in, bag(T)::in, bag(T)::out) is det.
:- func bag__subtract(bag(T), bag(T)) = bag(T).

	% The third bag is the union of the first 2 bags.
	% e.g. {1, 1, 2, 2} U {2, 2, 3, 3} = {1, 1, 2, 2, 2, 2, 3, 3}
	% If the two input bags are known to be unequal in size, then
	% making the first bag the larger bag will usually be more
	% efficient.
	%
:- pred bag__union(bag(T)::in, bag(T)::in, bag(T)::out) is det.
:- func bag__union(bag(T), bag(T)) = bag(T).

	% The third bag is the intersection of the first 2 bags.  Every
	% element in the third bag exists in both of the first 2 bags.
	% e.g. bag__intersect({1, 2, 2, 3, 3}, {2, 2, 3, 4}, {2, 2, 3}).
	%
:- pred bag__intersect(bag(T)::in, bag(T)::in, bag(T)::out) is det.
:- func bag__intersect(bag(T), bag(T)) = bag(T).

	% Fails if there is no intersection between the 2 bags.
	% bag__intersect(A, B) :- bag__intersect(A, B, C), not bag__is_empty(C).
	%
:- pred bag__intersect(bag(T)::in, bag(T)::in) is semidet.

	% The third bag is the smallest bag that has both the first two bags
	% as subbags. If an element X is present N times in one of the first
	% two bags, X will be present at least N times in the third bag.
	% E.g. {1, 1, 2} upper_bound {2, 2, 3} = {1, 1, 2, 2, 3}
	% If the two input bags are known to be unequal in size, then
	% making the first bag the larger bag will usually be more
	% efficient.
	%
:- pred bag__least_upper_bound(bag(T)::in, bag(T)::in, bag(T)::out) is det.
:- func bag__least_upper_bound(bag(T), bag(T)) = bag(T).

	% Fails if the first bag is not a subbag of the second.
	% bag__is_subbag(A, B). implies that every element in the bag A
	% is also in the bag B.  If an element is in bag A multiple times, it
	% must be in bag B at least as many times.
	% e.g. bag__is_subbag({1, 1, 2}, {1, 1, 2, 2, 3}).
	% e.g. bag__is_subbag({1, 1, 2}, {1, 2, 3}) :- fail.
	%
:- pred bag__is_subbag(bag(T)::in, bag(T)::in) is semidet.

	% Check whether a bag is empty.
	%
:- pred bag__is_empty(bag(T)::in) is semidet.

	% Fails if the bag is empty.
	%
:- pred bag__remove_smallest(bag(T)::in, T::out, bag(T)::out) is semidet.

	% Compares the two bags, and returns whether the first bag is a
	% subset (<), is equal (=), or is a superset (>) of the second.
	% bag__subset_compare(<, {apple, orange}, {apple, apple, orange}).
	% bag__subset_compare(=, {apple, orange}, {apple, orange}).
	% bag__subset_compare(>, {apple, apple, orange}, {apple, orange}).
	% bag__subset_compare(_, {apple, apple}, {orange, orange}) :- fail.
	%
:- pred bag__subset_compare(comparison_result::out, bag(T)::in, bag(T)::in)
	is semidet.

%--------------------------------------------------%
%--------------------------------------------------%


Node:benchmarking, Next:, Previous:bag, Up:Top

5 benchmarking


%--------------------------------------------------%
% Copyright (C) 1994-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: benchmarking.m.
% Main author: zs.
% Stability: medium to high.

% This module contains predicates that deal with the CPU time requirements
% of (various parts of) the program.

%--------------------------------------------------%
%--------------------------------------------------%

:- module benchmarking.
:- interface.

% `report_stats' is a non-logical procedure intended for use in profiling
% the performance of a program.
% It has the side-effect of reporting some memory and time usage statistics
% about the time period since the last call to report_stats to stderr.

:- impure pred report_stats is det.

% `report_full_memory_stats' is a non-logical procedure intended for use
% in profiling the memory usage of a program.  It has the side-effect of
% reporting a full memory profile to stderr.

:- impure pred report_full_memory_stats is det.

% benchmark_det(Pred, In, Out, Repeats, Time) is for benchmarking the
% det predicate Pred. We call Pred with the input In and the output Out,
% and return Out so that the caller can check the correctness of the
% benchmarked predicate. Since most systems do not have good facilities
% for measuring small times, the Repeats parameter allows the caller to
% specify how many times Pred should be called inside the timed interval.
% The number of milliseconds required to execute Pred with input In this
% many times is returned as Time.
%
% benchmark_func(Func, In, Out, Repeats, Time) does for functions exactly
% what benchmark_det does for predicates.

:- pred benchmark_det(pred(T1, T2), T1, T2, int, int).
:- mode benchmark_det(pred(in, out) is det, in, out, in, out) is cc_multi.
:- mode benchmark_det(pred(in, out) is cc_multi, in, out, in, out) is cc_multi.

:- pred benchmark_func(func(T1) = T2, T1, T2, int, int).
:- mode benchmark_func(func(in) = out is det, in, out, in, out) is cc_multi.

:- pred benchmark_det_io(pred(T1, T2, T3, T3), T1, T2, T3, T3, int, int).
:- mode benchmark_det_io(pred(in, out, di, uo) is det, in, out, di, uo,
	in, out) is cc_multi.

% benchmark_nondet(Pred, In, Count, Repeats, Time) is for benchmarking
% the nondet predicate Pred. benchmark_nondet is similar to benchmark_det,
% but it returns only a count of the solutions, rather than solutions
% themselves.  The number of milliseconds required to generate
% all solutions of Pred with input In Repeats times is returned as Time.

:- pred benchmark_nondet(pred(T1, T2), T1, int, int, int).
:- mode benchmark_nondet(pred(in, out) is nondet, in, out, in, out)
	is cc_multi.

%--------------------------------------------------%


Node:bimap, Next:, Previous:benchmarking, Up:Top

6 bimap


%--------------------------------------------------%
% Copyright (C) 1994-1995, 1997, 1999 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: bimap.m.
% Main author: conway.
% Stability: medium.
%
% This file provides a bijective 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.  A bimap also allows you to look up the Key given the Data.
%
% The implementation is a pair of maps.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module bimap.
:- interface.
:- import_module list, assoc_list.

%--------------------------------------------------%

:- type bimap(_K, _V).

%--------------------------------------------------%

	% Initialize an empty bimap.
:- pred bimap__init(bimap(_,_)).
:- mode bimap__init(out) is det.

:- func bimap__init = bimap(_,_).

	% Check whether a bimap is empty.
:- pred bimap__is_empty(bimap(_,_)).
:- mode bimap__is_empty(in) is semidet.

:- pred bimap__search(bimap(K,V), K, V).
:- mode bimap__search(in, in, out) is semidet.
:- mode bimap__search(in, out, in) is semidet.

:- func bimap__set(bimap(K,V), K, V) = bimap(K,V).

:- pred bimap__lookup(bimap(K,V), K, V).
:- mode bimap__lookup(in, in, out) is det.

:- func bimap__lookup(bimap(K,V), K) = V.

:- pred bimap__reverse_lookup(bimap(K,V), K, V).
:- mode bimap__reverse_lookup(in, out, in) is det.

:- pred bimap__insert(bimap(K,V), K, V, bimap(K,V)).
:- mode bimap__insert(in, in, in, out) is semidet.

:- pred bimap__set(bimap(K,V), K, V, bimap(K,V)).
:- mode bimap__set(in, in, in, out) is det.

	% Given a bimap, return a list of all the keys in the bimap
:- pred bimap__ordinates(bimap(K, _V), list(K)).
:- mode bimap__ordinates(in, out) is det.

:- func bimap__ordinates(bimap(K, _V)) = list(K).

	% Given a bimap, return a list of all the data values in the bimap
:- pred bimap__coordinates(bimap(_K, V), list(V)).
:- mode bimap__coordinates(in, out) is det.

:- func bimap__coordinates(bimap(_K, V)) = list(V).

	% convert a bimap to an association list
:- pred bimap__to_assoc_list(bimap(K,V), assoc_list(K,V)).
:- mode bimap__to_assoc_list(in, out) is det.

:- func bimap__to_assoc_list(bimap(K,V)) = assoc_list(K,V).

	% convert an association list to a bimap
:- pred bimap__from_assoc_list(assoc_list(K,V), bimap(K,V)).
:- mode bimap__from_assoc_list(in, out) is det.

:- func bimap__from_assoc_list(assoc_list(K,V)) = bimap(K,V).

/****
	% delete a key-value pair from a bimap
:- pred bimap__delete(bimap(K,V), K, V, bimap(K,V)).
:- mode bimap__delete(in, in, out, out) is det.
:- mode bimap__delete(in, out, in, out) is det.

:- pred bimap__from_corresponding_lists(list(K), list(V), bimap(K, V)).
:- mode bimap__from_corresponding_lists(in, in, out) is det.

:- func bimap__from_corresponding_lists(list(K), list(V)) = bimap(K, V).
****/

%--------------------------------------------------%

:- import_module map.

:- type bimap(K,V)	--->	bimap(map(K,V), map(V, K)).

%--------------------------------------------------%
%--------------------------------------------------%


Node:bintree, Next:, Previous:bimap, Up:Top

7 bintree


%--------------------------------------------------%
% Copyright (C) 1993-1995, 1997, 1999, 2002-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: bintree.m.
% Main author: conway.
% Stability: medium (obsolete).
%
% This module exists primarily for historical reasons.  It is unlikely
% to be useful, and may not be supported in future releases.
% You should use `map' instead.
%
% This file provides a straight-forward binary search tree implementation of
% a map (dictionary).
%
% bintree__insert, bintree__update, and bintree__set differ only in how they
% handle the case where the value being inserted already exists in the tree.
% `insert' will only insert new keys, and will fail if you attempt to insert
% an existing key into the tree. `update' will only allow you to modify the
% data for existing keys, and will fail if the key isn't already in the tree.
% `set' will always succeed; it will replace the old value for that key
% if the key was already in the tree, or insert a new node into the tree
% if the key wasn't already present.
%
%--------------------------------------------------%

:- module bintree.
:- interface.
:- import_module list, assoc_list.

:- type bintree(K, V).

:- pred bintree__init(bintree(K, V)::uo) is det.

:- pred bintree__insert(bintree(K, V)::in, K::in, V::in, bintree(K, V)::out)
	is semidet.

:- pred bintree__update(bintree(K, V)::in, K::in, V::in, bintree(K, V)::out)
	is semidet.

:- pred bintree__set(bintree(K, V), K, V, bintree(K, V)).
:- mode bintree__set(di, di, di, uo) is det.
:- mode bintree__set(in, in, in, out) is det.

:- func bintree__set(bintree(K, V), K, V) = bintree(K, V).

:- pred bintree__search(bintree(K, V), K, V).
:- mode bintree__search(in, in, in) is semidet.	% implied
:- mode bintree__search(in, in, out) is semidet.

:- pred bintree__lookup(bintree(K, V)::in, K::in, V::out) is det.
:- func bintree__lookup(bintree(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 bintree__lower_bound_search(bintree(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 bintree__lower_bound_lookup(bintree(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 bintree__upper_bound_search(bintree(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 bintree__upper_bound_lookup(bintree(K, V)::in, K::in, K::out, V::out)
	is det.

:- pred bintree__delete(bintree(K, V)::in, K::in, bintree(K, V)::out) is det.
:- func bintree__delete(bintree(K, V), K) = bintree(K, V).

:- pred bintree__remove(bintree(K, V)::in, K::in, V::out, bintree(K, V)::out)
	is semidet.

:- pred bintree__keys(bintree(K, _V)::in, list(K)::out) is det.
:- func bintree__keys(bintree(K, _V)) = list(K).

:- pred bintree__values(bintree(_K, V)::in, list(V)::out) is det.
:- func bintree__values(bintree(_K, V)) = list(V).

:- pred bintree__from_list(assoc_list(K, V)::in, bintree(K, V)::out) is det.
:- func bintree__from_list(assoc_list(K, V)) = bintree(K, V).

:- pred bintree__from_sorted_list(assoc_list(K, V)::in, bintree(K, V)::out)
	is det.
:- func bintree__from_sorted_list(assoc_list(K, V)) = bintree(K, V).

:- pred bintree__from_corresponding_lists(list(K)::in, list(V)::in,
	bintree(K, V)::out) is det.
:- func bintree__from_corresponding_lists(list(K), list(V)) = bintree(K, V).

:- pred bintree__to_list(bintree(K, V)::in, assoc_list(K, V)::out) is det.
:- func bintree__to_list(bintree(K, V)) = assoc_list(K, V).

	% count the number of elements in a tree
:- pred bintree__count(bintree(_K, _V)::in, int::out) is det.
:- func bintree__count(bintree(_K, _V)) = int.

	% count the depth of a tree
:- pred bintree__depth(bintree(_K, _V)::in, int::out) is det.
:- func bintree__depth(bintree(_K, _V)) = int.

:- pred bintree__branching_factor(bintree(_K, _V)::in, int::out, int::out)
	is det.

:- pred bintree__balance(bintree(K, V)::in, bintree(K, V)::out) is det.
:- func bintree__balance(bintree(K, V)) = bintree(K, V).

%--------------------------------------------------%


Node:bintree_set, Next:, Previous:bintree, Up:Top

8 bintree_set


%--------------------------------------------------%
% Copyright (C) 1994-1997, 1999-2000, 2003-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.
%--------------------------------------------------%

:- module bintree_set.

% Main authors: fjh.
% Stability: medium.

% This file provides an alternate implementation of the `set' ADT
% defined in module `set'.  See that file for comments about the semantics
% of the predicates.  This file implements sets as binary sorted trees,
% using module `bintree', and so provides different performance
% characteristics.

% bintree_set__is_member is a version of bintree_set__member
% with a more restricted mode, which is implemented much
% more efficiently using bintree__search.

%--------------------------------------------------%

:- interface.
:- import_module list.

:- type bintree_set(_T).

	% `bintree_set__list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'.

:- pred bintree_set__list_to_set(list(T)::in, bintree_set(T)::out) is det.
:- func bintree_set__list_to_set(list(T)) = bintree_set(T).

	% `bintree_set__sorted_list_to_set(List, Set)' is true iff
	% `Set' is the set containing only the members of `List'.
	% `List' must be sorted.

:- pred bintree_set__sorted_list_to_set(list(T)::in, bintree_set(T)::out)
	is det.
:- func bintree_set__sorted_list_to_set(list(T)) = bintree_set(T).

	% `bintree_set__list_to_bintree_set(Set, List)' is true iff
	% `List' is the list of all the members of `Set', in sorted
	% order.

:- pred bintree_set__to_sorted_list(bintree_set(T)::in, list(T)::out) is det.
:- func bintree_set__to_sorted_list(bintree_set(T)) = list(T).

	% `bintree_set__init(Set)' is true iff `Set' is an empty set.

:- pred bintree_set__init(bintree_set(T)::uo) is det.
:- func bintree_set__init = bintree_set(T).

:- pred bintree_set__singleton_set(bintree_set(T)::out, T::in) is det.

	% `bintree_set__equal(SetA, SetB)' is true iff
	% `SetA' and `SetB' contain the same elements.

:- pred bintree_set__equal(bintree_set(T)::in, bintree_set(T)::in) is semidet.

	% `bintree_set__subset(SetA, SetB)' is true iff `SetA' is a
	% subset of `SetB'.

:- pred bintree_set__subset(bintree_set(T)::in, bintree_set(T)::in) is semidet.

	% `bintree_set__superset(SetA, SetB)' is true iff `SetA' is a
	% superset of `SetB'.

:- pred bintree_set__superset(bintree_set(T)::in, bintree_set(T)::in)
	is semidet.

	% `bintree_set_member(X, Set)' is true iff `X' is a member of `Set'.

:- pred bintree_set__member(T, bintree_set(T)).
:- mode bintree_set__member(in, in) is semidet.
:- mode bintree_set__member(out, in) is nondet.

	% `bintree_set__is_member(X, Set)' is true
	% iff `X' is a member of `Set'.

:- pred bintree_set__is_member(T::in, bintree_set(T)::in) is semidet.

	% `bintree_set__contains(Set, X)' is true
	% iff `X' is a member of `Set'.

:- pred bintree_set__contains(bintree_set(T)::in, T::in) is semidet.

	% `bintree_set__insert(Set0, X, Set)' is true iff `Set' is the union of
	% `Set0' and the set containing only `X'.

:- pred bintree_set__insert(bintree_set(T), T, bintree_set(T)).
:- mode bintree_set__insert(di, di, uo) is det.
:- mode bintree_set__insert(in, in, out) is det.

:- func bintree_set__insert(bintree_set(T), T) = bintree_set(T).

	% `bintree_set__insert_list(Set0, Xs, Set)' is true iff `Set'
	% is the union of `Set0' and the set containing only the
	% members of `Xs'.

:- pred bintree_set__insert_list(bintree_set(T), list(T), bintree_set(T)).
:- mode bintree_set__insert_list(di, di, uo) is det.
:- mode bintree_set__insert_list(in, in, out) is det.

:- func bintree_set__insert_list(bintree_set(T), list(T)) = bintree_set(T).

	% `bintree_set__remove(Set0, X, Set)' is true iff `Set0' contains `X',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only `X', i.e.  if `Set' is the set which contains
	% all the elements of `Set0' except `X'.

:- pred bintree_set__remove(bintree_set(T), T, bintree_set(T)).
:- mode bintree_set__remove(in, in, out) is semidet.
% The following mode could be implemented, but hasn't been:
% :- mode bintree_set__remove(in, out, out) is nondet.

	% `bintree_set__remove_list(Set0, Xs, Set)' is true iff Xs does
	% not contain any duplicates, `Set0' contains every member of
	% `Xs', and `Set' is the relative complement of `Set0' and the
	% set containing only the members of `Xs'.

:- pred bintree_set__remove_list(bintree_set(T)::in, list(T)::in,
	bintree_set(T)::out) is semidet.

	% `bintree_set__delete(Set0, X, Set)' is true iff `Set' is the relative
	% complement of `Set0' and the set containing only `X', i.e.
	% if `Set' is the set which contains all the elements of `Set0'
	% except `X'.

:- pred bintree_set__delete(bintree_set(T)::in, T::in, bintree_set(T)::out)
	is det.
:- func bintree_set__delete(bintree_set(T), T) = bintree_set(T).

	% `bintree_set__delete_list(Set0, Xs, Set)' is true iff `Set'
	% is the relative complement of `Set0' and the set containing
	% only the members of `Xs'.

:- pred bintree_set__delete_list(bintree_set(T)::in, list(T)::in,
	bintree_set(T)::out) is det.
:- func bintree_set__delete_list(bintree_set(T), list(T)) = bintree_set(T).

	% `set_union(SetA, SetB, Set)' is true iff `Set' is the union of
	% `SetA' and `SetB'.  If the sets are known to be of different
	% sizes, then for efficiency make `SetA' the larger of the two.

:- pred bintree_set__union(bintree_set(T)::in, bintree_set(T)::in,
	bintree_set(T)::out) is det.
:- func bintree_set__union(bintree_set(T), bintree_set(T)) = bintree_set(T).

	% `set_intersect(SetA, SetB, Set)' is true iff `Set' is the
	% intersection of `SetA' and `SetB'.

:- pred bintree_set__intersect(bintree_set(T)::in, bintree_set(T)::in,
	bintree_set(T)::out) is det.
:- func bintree_set__intersect(bintree_set(T), bintree_set(T))
	= bintree_set(T).

%--------------------------------------------------%


Node:bitmap, Next:, Previous:bintree_set, Up:Top

9 bitmap


%--------------------------------------------------%
% vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
%--------------------------------------------------%
% Copyright (C) 2001-2002, 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: bitmap.m
% Main author: rafe
% Stability: low
%
% Efficient bitmap implementation.
%
% CAVEAT: the user is referred to the documentation in the header
% of array.m regarding programming with unique objects (the compiler
% does not currently recognise them, hence we are forced to use
% non-unique modes until the situation is rectified; this places
% a small burden on the programmer to ensure the correctness of his
% code that would otherwise be assured by the compiler.)
%
%--------------------------------------------------%

:- module bitmap.

:- interface.

:- import_module array, int, bool.

:- type bitmap.

:- inst bitmap    == array.
:- inst uniq_bitmap == uniq_array.
:- mode bitmap_ui == array_ui.
:- mode bitmap_di == array_di.
:- mode bitmap_uo == array_uo.

    % new(N, B) creates a bitmap of size N (indexed 0 .. N-1)
    % setting each bit if B = yes and clearing each bit if B = no.
    % An exception is thrown if N is negative.
    %
:- func new(int, bool) = bitmap.
:- mode new(in, in) = bitmap_uo is det.

    % Returns the number of bits in a bitmap.
    %
:- func num_bits(bitmap) = int.
:- mode num_bits(bitmap_ui) = out is det.
:- mode num_bits(in) = out is det.

    % set(BM, I), clear(BM, I) and flip(BM, I) set, clear and flip
    % bit I in BM respectively.
    %
:- func set(bitmap, int) = bitmap.
:- mode set(bitmap_di, in) = bitmap_uo is det.

:- func clear(bitmap, int) = bitmap.
:- mode clear(bitmap_di, in) = bitmap_uo is det.

:- func flip(bitmap, int) = bitmap.
:- mode flip(bitmap_di, in) = bitmap_uo is det.

    % Unsafe versions of the above: if the index is out of range
    % then behaviour is undefined and bad things are likely to happen.
    %
:- func unsafe_set(bitmap, int) = bitmap.
:- mode unsafe_set(bitmap_di, in) = bitmap_uo is det.

:- func unsafe_clear(bitmap, int) = bitmap.
:- mode unsafe_clear(bitmap_di, in) = bitmap_uo is det.

:- func unsafe_flip(bitmap, int) = bitmap.
:- mode unsafe_flip(bitmap_di, in) = bitmap_uo is det.

    % is_set(BM, I) and is_clear(BM, I) succeed iff bit I in BM
    % is set or clear respectively.
    %
:- pred is_set(bitmap, int).
:- mode is_set(bitmap_ui, in) is semidet.
:- mode is_set(in, in) is semidet.

:- pred is_clear(bitmap, int).
:- mode is_clear(bitmap_ui, in) is semidet.
:- mode is_clear(in, in) is semidet.

    % Unsafe versions of the above: if the index is out of range
    % then behaviour is undefined and bad things are likely to happen.
    %
:- pred unsafe_is_set(bitmap, int).
:- mode unsafe_is_set(bitmap_ui, in) is semidet.
:- mode unsafe_is_set(in, in) is semidet.

:- pred unsafe_is_clear(bitmap, int).
:- mode unsafe_is_clear(bitmap_ui, in) is semidet.
:- mode unsafe_is_clear(in, in) is semidet.

    % get(BM, I) returns `yes' if is_set(BM, I) and `no' otherwise.
    %
:- func get(bitmap, int) = bool.
:- mode get(bitmap_ui, in) = out is det.
:- mode get(in, in) = out is det.

    % Unsafe versions of the above: if the index is out of range
    % then behaviour is undefined and bad things are likely to happen.
    %
:- func unsafe_get(bitmap, int) = bool.
:- mode unsafe_get(bitmap_ui, in) = out is det.
:- mode unsafe_get(in, in) = out is det.

    % Create a new copy of a bitmap.
    %
:- func copy(bitmap) = bitmap.
:- mode copy(bitmap_ui) = bitmap_uo is det.

    % Set operations; the second argument is altered in all cases.
    %
:- func complement(bitmap) = bitmap.
:- mode complement(bitmap_di) = bitmap_uo is det.

:- func union(bitmap, bitmap) = bitmap.
:- mode union(bitmap_ui, bitmap_di) = bitmap_uo is det.

:- func intersect(bitmap, bitmap) = bitmap.
:- mode intersect(bitmap_ui, bitmap_di) = bitmap_uo is det.

:- func difference(bitmap, bitmap) = bitmap.
:- mode difference(bitmap_ui, bitmap_di) = bitmap_uo is det.

    % resize(BM, N, B) resizes bitmap BM to have N bits; if N is
    % smaller than the current number of bits in BM then the excess
    % are discarded.  If N is larger than the current number of bits
    % in BM then the new bits are set if B = yes and cleared if
    % B = no.
    %
:- func resize(bitmap, int, bool) = bitmap.
:- mode resize(bitmap_di, in, in) = bitmap_uo is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:bool, Next:, Previous:bitmap, Up:Top

10 bool


%--------------------------------------------------%
% Copyright (C) 1996-1997,2000,2002-2003 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: bool.m.
% Main authors: fjh, zs.
% Stability: medium to high.

% This module exports the boolean type `bool' and some operations on bools.

%--------------------------------------------------%
%--------------------------------------------------%

:- module bool.

:- interface.

:- import_module enum, list.

%--------------------------------------------------%

% The boolean type.
% Unlike most languages, we use `yes' and `no' as boolean constants
% rather than `true' and `false'.  This is to avoid confusion
% with the predicates `true' and `fail'.

:- type bool ---> no ; yes.

:- instance enum(bool).

:- func bool__or(bool, bool) = bool.
:- pred bool__or(bool, bool, bool).
:- mode bool__or(in, in, out) is det.

:- func bool__or_list(list(bool)) = bool.
:- pred bool__or_list(list(bool), bool).
:- mode bool__or_list(in, out) is det.

:- func bool__and(bool, bool) = bool.
:- pred bool__and(bool, bool, bool).
:- mode bool__and(in, in, out) is det.

:- func bool__and_list(list(bool)) = bool.
:- pred bool__and_list(list(bool), bool).
:- mode bool__and_list(in, out) is det.

:- func bool__not(bool) = bool.
:- pred bool__not(bool, bool).
:- mode bool__not(in, out) is det.

	% pred_to_bool(P) = (if P then yes else no).
:- func pred_to_bool((pred)) = bool.
:- mode pred_to_bool((pred) is semidet) = out is det.

%--------------------------------------------------%


Node:bt_array, Next:, Previous:bool, Up:Top

11 bt_array


%--------------------------------------------------%
% Copyright (C) 1997, 1999-2000, 2002-2003 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: bt_array.m
% Main author: bromage.
% Stability: medium-low

% This file contains a set of predicates for generating an manipulating
% a bt_array data structure.  This implementation allows O(log n) access
% and update time, and does not require the bt_array to be unique.  If you
% need O(1) access/update time, use the array datatype instead.
% (`bt_array' is supposed to stand for either "binary tree array"
% or "backtrackable array".)

% Implementation obscurity: This implementation is biased towards larger
% indices.  The access/update time for a bt_array of size N with index I
% is actually O(log(N-I)).  The reason for this is so that the resize
% operations can be optimised for a (possibly very) common case, and to
% exploit accumulator recursion in some operations.  See the documentation
% of bt_array__resize and bt_array__shrink for more details.

%--------------------------------------------------%
%--------------------------------------------------%

:- module bt_array.
:- interface.
:- import_module int, list.

:- type bt_array(T).

%--------------------------------------------------%

	% bt_array__make_empty_array(Low, Array) is true iff Array is a
	% bt_array of size zero starting at index Low.
:- pred bt_array__make_empty_array(int, bt_array(T)).
:- mode bt_array__make_empty_array(in, out) is det.

:- func bt_array__make_empty_array(int) = bt_array(T).

	% bt_array__init(Low, High, Init, Array) is true iff Array is a
	% bt_array with bounds from Low to High whose elements each equal Init.
:- pred bt_array__init(int, int, T, bt_array(T)).
:- mode bt_array__init(in, in, in, out) is det. % want a bt_array_skeleton?

:- func bt_array__init(int, int, T) = bt_array(T).

%--------------------------------------------------%

	% array__min returns the lower bound of the array
:- pred bt_array__min(bt_array(_T), int).
:- mode bt_array__min(in, out) is det.

:- func bt_array__min(bt_array(_T)) = int.

	% array__max returns the upper bound of the array
:- pred bt_array__max(bt_array(_T), int).
:- mode bt_array__max(in, out) is det.

:- func bt_array__max(bt_array(_T)) = int.

	% array__size returns the length of the array,
	% i.e. upper bound - lower bound + 1.
:- pred bt_array__size(bt_array(_T), int).
:- mode bt_array__size(in, out) is det.

:- func bt_array__size(bt_array(_T)) = int.

	% bt_array__bounds returns the upper and lower bounds of a bt_array.
:- pred bt_array__bounds(bt_array(_T), int, int).
:- mode bt_array__bounds(in, out, out) is det.

	% bt_array__in_bounds checks whether an index is in the bounds
	% of a bt_array
:- pred bt_array__in_bounds(bt_array(_T), int).
:- mode bt_array__in_bounds(in, in) is semidet.

%--------------------------------------------------%

	% bt_array__lookup returns the Nth element of a bt_array.
	% It is an error if the index is out of bounds.
:- pred bt_array__lookup(bt_array(T), int, T).
:- mode bt_array__lookup(in, in, out) is det.

:- func bt_array__lookup(bt_array(T), int) = T.

	% bt_array__semidet_lookup is like bt_array__lookup except that
	% it fails if the index is out of bounds.
:- pred bt_array__semidet_lookup(bt_array(T), int, T).
:- mode bt_array__semidet_lookup(in, in, out) is semidet.

	% bt_array__set sets the nth element of a bt_array, and returns the
	% resulting bt_array.
	% It is an error if the index is out of bounds.
:- pred bt_array__set(bt_array(T), int, T, bt_array(T)).
:- mode bt_array__set(in, in, in, out) is det.

:- func bt_array__set(bt_array(T), int, T) = bt_array(T).

	% bt_array__set sets the nth element of a bt_array, and returns the
	% resulting bt_array (good opportunity for destructive update ;-).
	% It fails if the index is out of bounds.
:- pred bt_array__semidet_set(bt_array(T), int, T, bt_array(T)).
:- mode bt_array__semidet_set(in, in, in, out) is semidet.

	% `bt_array__resize(BtArray0, Lo, Hi, Item, BtArray)' is true
	% if BtArray is a bt_array created by expanding or shrinking
	% BtArray0 to fit the bounds (Lo,Hi).  If the new bounds are
	% not wholly contained within the bounds of BtArray0, Item is
	% used to fill out the other places.
	%
	% Note: This operation is optimised for the case where the
	% lower bound of the new bt_array is the same as that of
	% the old bt_array.  In that case, the operation takes time
	% proportional to the absolute difference in size between
	% the two bt_arrays.  If this is not the case, it may take
	% time proportional to the larger of the two bt_arrays.
:- pred bt_array__resize(bt_array(T), int, int, T, bt_array(T)).
:- mode bt_array__resize(in, in, in, in, out) is det.

:- func bt_array__resize(bt_array(T), int, int, T) = bt_array(T).

	% `bt_array__shrink(BtArray0, Lo, Hi, Item, BtArray)' is true
	% if BtArray is a bt_array created by shrinking BtArray0 to
	% fit the bounds (Lo,Hi).  It is an error if the new bounds
	% are not wholly within the bounds of BtArray0.
	%
	% Note: This operation is optimised for the case where the
	% lower bound of the new bt_array is the same as that of
	% the old bt_array.  In that case, the operation takes time
	% proportional to the absolute difference in size between
	% the two bt_arrays.  If this is not the case, it may take
	% time proportional to the larger of the two bt_arrays.
:- pred bt_array__shrink(bt_array(T), int, int, bt_array(T)).
:- mode bt_array__shrink(in, in, in, out) is det.

:- func bt_array__shrink(bt_array(T), int, int) = bt_array(T).

	% `bt_array__from_list(Low, List, BtArray)' takes a list (of
	% possibly zero length), and returns a bt_array containing
	% those elements in the same order that they occurred in the
	% list.  The lower bound of the new array is `Low'.
:- pred bt_array__from_list(int, list(T), bt_array(T)).
:- mode bt_array__from_list(in, in, out) is det.

:- func bt_array__from_list(int, list(T)) = bt_array(T).

	% bt_array__to_list takes a bt_array and returns a list containing
	% the elements of the bt_array in the same order that they
	% occurred in the bt_array.
:- pred bt_array__to_list(bt_array(T), list(T)).
:- mode bt_array__to_list(in, out) is det.

:- func bt_array__to_list(bt_array(T)) = list(T).

	% bt_array__fetch_items takes a bt_array and a lower and upper
	% index, and places those items in the bt_array between these
	% indices into a list.  It is an error if either index is
	% out of bounds.
:- pred bt_array__fetch_items(bt_array(T), int, int, list(T)).
:- mode bt_array__fetch_items(in, in, in, out) is det.

:- func bt_array__fetch_items(bt_array(T), int, int) = list(T).

	% bt_array__bsearch takes a bt_array, an element to be matched
	% and a comparison predicate and returns the position of
	% the first occurrence in the bt_array of an element which is
	% equivalent to the given one in the ordering provided.
	% Assumes the bt_array is sorted according to this ordering.
	% Fails if the element is not present.
:- pred bt_array__bsearch(bt_array(T), T, comparison_pred(T), int).
:- mode bt_array__bsearch(in, in, in(comparison_pred), out) is semidet.

	% Field selection for arrays.
	% Array ^ elem(Index) = bt_array__lookup(Array, Index).
:- func bt_array__elem(int, bt_array(T)) = T.

	% Field update for arrays.
	% (Array ^ elem(Index) := Value) = bt_array__set(Array, Index, Value).
:- func 'bt_array__elem :='(int, bt_array(T), T) = bt_array(T).

%--------------------------------------------------%


Node:builtin, Next:, Previous:bt_array, Up:Top

12 builtin


%--------------------------------------------------%
% Copyright (C) 1994-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: builtin.m.
% Main author: fjh.
% Stability: low.

% This file is automatically imported into every module.
% It is intended for things that are part of the language,
% but which are implemented just as normal user-level code
% rather than with special coding in the compiler.

%--------------------------------------------------%
%--------------------------------------------------%

:- module builtin.
:- interface.

%--------------------------------------------------%

% TYPES.

% The types `character', `int', `float', and `string',
% and tuple types `{}', `{T}', `{T1, T2}', ...
% and the types `pred', `pred(T)', `pred(T1, T2)', `pred(T1, T2, T3)', ...
% and `func(T1) = T2', `func(T1, T2) = T3', `func(T1, T2, T3) = T4', ...
% are builtin and are implemented using special code in the
% type-checker.  (XXX TODO: report an error for attempts to redefine
% these types.)

% The type c_pointer can be used by predicates which use the C interface.
:- type c_pointer.

%--------------------------------------------------%

% INSTS.

% The standard insts `free', `ground', and `bound(...)' are builtin
% and are implemented using special code in the parser and mode-checker.

% So are the standard unique insts `unique', `unique(...)',
% `mostly_unique', `mostly_unique(...)', and `clobbered'.
% The name `dead' is allowed as a synonym for `clobbered'.
% Similarly `mostly_dead' is a synonym for `mostly_clobbered'.

:- inst dead = clobbered.
:- inst mostly_dead = mostly_clobbered.

% The `any' inst used for the constraint solver interface is also builtin.

% Higher-order predicate insts `pred(<modes>) is <detism>'
% and higher-order functions insts `func(<modes>) = <mode> is det'
% are also builtin.

%--------------------------------------------------%

% MODES.

% The standard modes.

:- mode unused :: (free -> free).
:- mode output :: (free -> ground).
:- mode input :: (ground -> ground).

:- mode in :: (ground -> ground).
:- mode out :: (free -> ground).

:- mode in(Inst) :: (Inst -> Inst).
:- mode out(Inst) :: (free -> Inst).
:- mode di(Inst) :: (Inst -> clobbered).
:- mode mdi(Inst) :: (Inst -> mostly_clobbered).

% Unique modes.  These are still not fully implemented.

% unique output
:- mode uo :: free -> unique.

% unique input
:- mode ui :: unique -> unique.

% destructive input
:- mode di :: unique -> clobbered.

% "Mostly" unique modes (unique except that that may be referenced
% again on backtracking).

% mostly unique output
:- mode muo :: free -> mostly_unique.

% mostly unique input
:- mode mui :: mostly_unique -> mostly_unique.

% mostly destructive input
:- mode mdi :: mostly_unique -> mostly_clobbered.

% Higher-order predicate modes are builtin.

%--------------------------------------------------%

% PREDICATES.

% Most of these probably ought to be moved to another
% module in the standard library such as std_util.m.

% copy/2 makes a deep copy of a data structure.  The resulting copy is a
% `unique' value, so you can use destructive update on it.

:- pred copy(T, T).
:- mode copy(ui, uo) is det.
:- mode copy(in, uo) is det.

% unsafe_promise_unique/2 is used to promise the compiler that you have a
% `unique' copy of a data structure, so that you can use destructive update.
% It is used to work around limitations in the current support for unique
% modes.  `unsafe_promise_unique(X, Y)' is the same as `Y = X' except that
% the compiler will assume that `Y' is unique.
%
% Note that misuse of this predicate may lead to unsound results:
% if there is more than one reference to the data in question,
% i.e. it is not `unique', then the behaviour is undefined.
% (If you lie to the compiler, the compiler will get its revenge!)

:- pred unsafe_promise_unique(T, T).
:- mode unsafe_promise_unique(in, uo) is det.

:- func unsafe_promise_unique(T) = T.
:- mode unsafe_promise_unique(in) = uo is det.

% A synonym for fail/0; the name is more in keeping with Mercury's
% declarative style rather than its Prolog heritage.

:- pred false.
:- mode false is failure.

%--------------------------------------------------%

% A call to the function `promise_only_solution(Pred)' constitutes a
% promise on the part of the caller that `Pred' has at most one solution,
% i.e. that `not some [X1, X2] (Pred(X1), Pred(X2), X1 \= X2)'.
% `promise_only_solution(Pred)' presumes that this assumption is
% satisfied, and returns the X for which Pred(X) is true, if
% there is one.
%
% You can use `promise_only_solution' as a way of
% introducing `cc_multi' or `cc_nondet' code inside a
% `det' or `semidet' procedure.
%
% Note that misuse of this function may lead to unsound results:
% if the assumption is not satisfied, the behaviour is undefined.
% (If you lie to the compiler, the compiler will get its revenge!)

:- func promise_only_solution(pred(T)) = T.
:- mode promise_only_solution(pred(out) is cc_multi) = out is det.
:- mode promise_only_solution(pred(uo) is cc_multi) = uo is det.
:- mode promise_only_solution(pred(out) is cc_nondet) = out is semidet.
:- mode promise_only_solution(pred(uo) is cc_nondet) = uo is semidet.

% `promise_only_solution_io' is like `promise_only_solution', but
% for procedures with unique modes (e.g. those that do IO).
%
% A call to `promise_only_solution_io(P, X, IO0, IO)' constitutes
% a promise on the part of the caller that for the given IO0,
% there is only one value of `X' and `IO' for which `P(X, IO0, IO)' is true.
% `promise_only_solution_io(P, X, IO0, IO)' presumes that this assumption
% is satisfied, and returns the X and IO for which `P(X, IO0, IO)' is true.
%
% Note that misuse of this predicate may lead to unsound results:
% if the assumption is not satisfied, the behaviour is undefined.
% (If you lie to the compiler, the compiler will get its revenge!)

:- pred promise_only_solution_io(pred(T, IO, IO), T, IO, IO).
:- mode promise_only_solution_io(pred(out, di, uo) is cc_multi,
		out, di, uo) is det.

%--------------------------------------------------%

	% unify(X, Y) is true iff X = Y.
:- pred unify(T::in, T::in) is semidet.

	% For use in defining user-defined unification predicates.
	% The relation defined by a value of type `unify', must be an
	% equivalence relation; that is, it must be symmetric, reflexive,
	% and transitive.
:- type unify(T) == pred(T, T).
:- inst unify == (pred(in, in) is semidet).

:- type comparison_result ---> (=) ; (<) ; (>).

	% compare(Res, X, Y) binds Res to =, <, or >
	% depending on wheither X is =, <, or > Y in the
	% standard ordering.
:- pred compare(comparison_result, T, T).
	% Note to implementors: the modes must appear in this order:
	% compiler/higher_order.m depends on it, as does
	% compiler/simplify.m (for the inequality simplification.)
:- mode compare(uo, in, in) is det.
:- mode compare(uo, ui, ui) is det.
:- mode compare(uo, ui, in) is det.
:- mode compare(uo, in, ui) is det.

	% For use in defining user-defined comparison predicates.
	% For a value `ComparePred' of type `compare', the following
	% conditions must hold:
	%
	% - the relation
	%	compare_eq(X, Y) :- ComparePred((=), X, Y).
	%   must be an equivalence relation; that is, it must be symmetric,
	%   reflexive, and transitive.
	%
	% - the relations
	%	compare_leq(X, Y) :-
	%		ComparePred(R, X, Y), (R = (=) ; R = (<)).
	%	compare_geq(X, Y) :-
	%		ComparePred(R, X, Y), (R = (=) ; R = (>)).
	%   must be total order relations: that is they must be antisymmetric,
	%   reflexive and transitive.
:- type compare(T) == pred(comparison_result, T, T).
:- inst compare == (pred(uo, in, in) is det).

	% ordering(X, Y) = R <=> compare(R, X, Y)
	%
:- func ordering(T, T) = comparison_result.

	% The standard inequalities defined in terms of compare/3.
	% XXX The ui modes are commented out because they don't yet
	% work properly.
	%
:- pred T  @<  T.
:- mode in @< in is semidet.
% :- mode ui @< in is semidet.
% :- mode in @< ui is semidet.
% :- mode ui @< ui is semidet.

:- pred T  @=<  T.
:- mode in @=< in is semidet.
% :- mode ui @=< in is semidet.
% :- mode in @=< ui is semidet.
% :- mode ui @=< ui is semidet.

:- pred T  @>  T.
:- mode in @> in is semidet.
% :- mode ui @> in is semidet.
% :- mode in @> ui is semidet.
% :- mode ui @> ui is semidet.

:- pred T  @>=  T.
:- mode in @>= in is semidet.
% :- mode ui @>= in is semidet.
% :- mode in @>= ui is semidet.
% :- mode ui @>= ui is semidet.

	% Values of types comparison_pred/1 and comparison_func/1 are used
	% by predicates and functions which depend on an ordering on a given
	% type, where this ordering is not necessarily the standard ordering.
	% In addition to the type, mode and determinism constraints, a
	% comparison predicate C is expected to obey two other laws.
	% For all X, Y and Z of the appropriate type, and for all
	% comparison_results R:
	%	1) C(X, Y, (>)) if and only if C(Y, X, (<))
	%	2) C(X, Y, R) and C(Y, Z, R) implies C(X, Z, R).
	% Comparison functions are expected to obey analogous laws.
	%
	% Note that binary relations <, > and = can be defined from a
	% comparison predicate or function in an obvious way.  The following
	% facts about these relations are entailed by the above constraints:
	% = is an equivalence relation (not necessarily the usual equality),
	% and the equivalence classes of this relation are totally ordered
	% with respect to < and >.
:- type comparison_pred(T) == pred(T, T, comparison_result).
:- inst comparison_pred(I) == (pred(in(I), in(I), out) is det).
:- inst comparison_pred == comparison_pred(ground).

:- type comparison_func(T) == (func(T, T) = comparison_result).
:- inst comparison_func(I) == (func(in(I), in(I)) = out is det).
:- inst comparison_func == comparison_func(ground).

% In addition, the following predicate-like constructs are builtin:
%
%	:- pred (T = T).
%	:- pred (T \= T).
%	:- pred (pred , pred).
%	:- pred (pred ; pred).
%	:- pred (\+ pred).
%	:- pred (not pred).
%	:- pred (pred -> pred).
%	:- pred (if pred then pred).
%	:- pred (if pred then pred else pred).
%	:- pred (pred => pred).
%	:- pred (pred <= pred).
%	:- pred (pred <=> pred).
%
%	(pred -> pred ; pred).
%	some Vars pred
%	all Vars pred
%	call/N

%--------------------------------------------------%


Node:char, Next:, Previous:builtin, Up:Top

13 char


%--------------------------------------------------%
% Copyright (C) 1994-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: char.m.
% Main author: fjh.
% Stability: high.

% This module defines some predicates that manipulate characters.

% The set of characters which are supported and the mapping from
% characters to integer values are both implementation-dependent.

% Originally we used `character' rather than `char' for the type name
% because `char' was used by NU-Prolog to mean something different.
% But now we use `char' and the use of `character' is discouraged.

%--------------------------------------------------%
%--------------------------------------------------%

:- module char.
:- interface.
:- import_module enum.

%--------------------------------------------------%

:- type char == character.

:- instance enum(character).

	% Convert a character to its corresponding numerical code
	% (integer value).
	% Beware that the mapping from characters to numerical codes
	% is implementation-dependent; there is no guarantee that
	% the integer values for characters will fit in 8 bits.
	% Furthermore, the value returned from char__to_int might be
	% different than the byte(s) used to store the character in a file.
	% There is also no guarantee that characters created using
	% `char__to_int(out, in)' can be written to files or
	% to the standard output or standard error streams.
	% For example, an implementation might represent characters
	% using Unicode, but store files in an 8-bit national character set.
:- func char__to_int(char) = int.
:- pred char__to_int(char, int).
:- mode char__to_int(in, out) is det.
:- mode char__to_int(in, in) is semidet.	% implied
:- mode char__to_int(out, in) is semidet.

	% Returns the maximum numerical character code.
:- func char__max_char_value = int.
:- pred char__max_char_value(int::out) is det.

	% Returns the minimum numerical character code.
:- func char__min_char_value = int.
:- pred char__min_char_value(int::out) is det.

	% Convert a character to uppercase.
:- func char__to_upper(char) = char.
:- pred char__to_upper(char::in, char::out) is det.

	% Convert a character to lowercase.
:- func char__to_lower(char) = char.
:- pred char__to_lower(char::in, char::out) is det.

	% char__lower_upper(Lower, Upper) is true iff
	% Lower is a lower-case letter and Upper is the corresponding
	% upper-case letter.
:- pred char__lower_upper(char, char).
:- mode char__lower_upper(in, out) is semidet.
:- mode char__lower_upper(out, in) is semidet.

	% True iff the character is whitespace, i.e. a space, tab,
	% newline, carriage return, form-feed, or vertical tab.
:- pred char__is_whitespace(char::in) is semidet.

	% True iff the character is an uppercase letter.
:- pred char__is_upper(char::in) is semidet.

	% True iff the character is a lowercase letter.
:- pred char__is_lower(char::in) is semidet.

	% True iff the character is a letter.
:- pred char__is_alpha(char::in) is semidet.

	% True iff the character is a letter or digit.
:- pred char__is_alnum(char::in) is semidet.

	% True iff the character is a letter or an underscore.
:- pred char__is_alpha_or_underscore(char::in) is semidet.

	% True iff the character is a letter, a digit or an underscore.
:- pred char__is_alnum_or_underscore(char::in) is semidet.

	% True iff the character is a decimal digit (0-9).
:- pred char__is_digit(char::in) is semidet.

	% True iff the character is a binary digit (0 or 1).
:- pred char__is_binary_digit(char::in) is semidet.

	% True iff the character is a octal digit (0-7).
:- pred char__is_octal_digit(char::in) is semidet.

	% True iff the character is a hexadecimal digit (0-9, a-f, A-F).
:- pred char__is_hex_digit(char::in) is semidet.

	% Succeeds if char is a decimal digit (0-9) or letter (a-z or A-Z).
	% Returns the character's value as a digit (0-9 or 10-35).
:- pred char__digit_to_int(char::in, int::out) is semidet.

	% char__int_to_uppercase_digit(Int, DigitChar):
	% True iff `Int' is an integer in the range 0-35 and
	% `DigitChar' is a decimal digit or uppercase letter
	% whose value as a digit is `Int'.
:- pred char__int_to_digit(int, char).
:- mode char__int_to_digit(in, out) is semidet.
:- mode char__int_to_digit(out, in) is semidet.

	% Returns a decimal digit or uppercase letter corresponding to the
	% value.
	% Calls error/1 if the integer is not in the range 0-35.
:- func char__det_int_to_digit(int) = char.
:- pred char__det_int_to_digit(int::in, char::out) is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:construct, Next:, Previous:char, Up:Top

14 construct


% vim: ft=mercury ts=4 sw=4 et
%--------------------------------------------------%
% Copyright (C) 2002-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: construct.m.
% Main author: zs.
% Stability: low.

%--------------------------------------------------%
%--------------------------------------------------%

:- module construct.

:- interface.

:- import_module std_util, list, type_desc.

    % num_functors(TypeInfo)
    %
    % Returns the number of different functors for the top-level
    % type constructor of the type specified by TypeInfo, or -1
    % if the type is not a discriminated union type.
    %
    % The functors of a discriminated union type are numbered from
    % zero to N-1, where N is the value returned by num_functors.
    % The functors are numbered in lexicographic order. If two
    % functors have the same name, the one with the lower arity
    % will have the lower number.
    %
:- func num_functors(type_desc__type_desc) = int.

    % get_functor(Type, FunctorNumber, FunctorName, Arity, ArgTypes)
    %
    % Binds FunctorName and Arity to the name and arity of functor number
    % FunctorNumber for the specified type, and binds ArgTypes to the
    % type_descs for the types of the arguments of that functor.
    % Fails if the type is not a discriminated union type, or if
    % FunctorNumber is out of range.
    %
:- pred get_functor(type_desc__type_desc::in, int::in, string::out, int::out,
        list(type_desc__type_desc)::out) is semidet.

    % get_functor(Type, FunctorNumber, FunctorName, Arity, ArgTypes,
    %   ArgNames)
    %
    % Binds FunctorName and Arity to the name and arity of functor number
    % FunctorNumber for the specified type, ArgTypes to the type_descs
    % for the types of the arguments of that functor, and ArgNames to the
    % field name of each functor argument, if any.  Fails if the type is
    % not a discriminated union type, or if FunctorNumber is out of range.
    %
:- pred get_functor(type_desc__type_desc::in, int::in, string::out, int::out,
        list(type_desc__type_desc)::out, list(maybe(string))::out)
        is semidet.

    % get_functor_ordinal(Type, I, Ordinal)
    %
    % Returns Ordinal, where Ordinal is the position in declaration order
    % for the specified type of the function symbol that is in position I
    % in lexicographic order. Fails if the type is not a discriminated
    % union type, or if I is out of range.
:- pred get_functor_ordinal(type_desc__type_desc::in, int::in, int::out)
    is semidet.

    % construct(TypeInfo, I, Args) = Term
    %
    % Returns a term of the type specified by TypeInfo whose functor
    % is functor number I of the type given by TypeInfo, and whose
    % arguments are given by Args.  Fails if the type is not a
    % discriminated union type, or if I is out of range, or if the
    % number of arguments supplied doesn't match the arity of the selected
    % functor, or if the types of the arguments do not match
    % the expected argument types of that functor.
    %
:- func construct(type_desc__type_desc::in, int::in, list(univ)::in)
    = (univ::out) is semidet.

    % construct_tuple(Args) = Term
    %
    % Returns a tuple whose arguments are given by Args.
:- func construct_tuple(list(univ)) = univ.

%--------------------------------------------------%


Node:cord, Next:, Previous:construct, Up:Top

15 cord


%--------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%--------------------------------------------------%
% Copyright (C) 2002-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.
%--------------------------------------------------%
%
% Ralph Becket <rafe@cs.mu.oz.au>
% Mon Feb  3 12:27:53 EST 2003
%
% A cord is a sequence sequence type supporting O(1) consing and
% concatenation.  A cord is essentially a tree structure with data stored
% in the leaf nodes.  Joining two cords together to construct a new cord
% is therefore an O(1) operation.
%
% This data type is intended for situations where efficient, linearised
% collection of data is required.
%
% While this data type presents a list-like interface, calls to list/1 and
% head_tail/3 in particular are O(n) in the size of the cord.
%
%--------------------------------------------------%

:- module cord.

:- interface.

:- import_module list, int.

    % Cords that contain the same members in the same order will not
    % necessarily have the same representation and will, therefore,
    % not necessarily either unify or compare as equal.
    %
    % The exception to this rule is that the empty cord does have a
    % unique representation.
    %
:- type cord(T).

    % The list of data in a cord:
    %
    %   list(empty        ) = []
    %   list(from_list(Xs)) = Xs
    %   list(cons(X, C)   ) = [X | list(C)]
    %   list(TA ++ TB     ) = list(TA) ++ list(TB)
    %
:- func list(cord(T)) = list(T).

    % The unique representation for the empty cord:
    %
    %   list(empty) = []
    %
:- func empty = cord(T).

    % list(singleton(X)) = [X]
    %
:- func singleton(T) = cord(T).

    % list(from_list(Xs)) = Xs
    % An O(1) operation.
    %
:- func from_list(list(T)) = cord(T).

    % list(cons(X, C)) = [X | list(C)]
    % An O(1) operation.
    %
:- func cons(T, cord(T)) = cord(T).

    % list(snoc(C, X)) = list(C) ++ [X]
    % An O(1) operation.
    %
:- func snoc(cord(T), T) = cord(T).

    % list(CA ++ CB) = list(CA) ++ list(CB)
    % An O(1) operation.
    %
:- func cord(T) ++ cord(T) = cord(T).

    %     head_tail(C0, X, C)  =>  list(C0) = [X | list(C)]
    % not head_tail(C0, _, _)  =>  C0 = empty
    % An O(n) operation, although traversing an entire cord with
    % head_tail/3 gives O(1) amortized cost for each call.
    %
:- pred head_tail(cord(T)::in, T::out, cord(T)::out) is semidet.

    % length(C) = list.length(list(C))
    % An O(n) operation.
    %
:- func length(cord(T)) = int.

    % member(X, C) <=> list.member(X, list(C)).
    %
:- pred member(T::out, cord(T)::in) is nondet.

    % list(map(F, C)) = list.map(F, list(C))
    %
:- func map(func(T) = U, cord(T)) = cord(U).

    % foldl(F, C, A) = list.foldl(F, list(C), A).
    %
:- func foldl(func(T, U) = U, cord(T), U) = U.

    % foldr(F, C, A) = list.foldr(F, list(C), A).
    %
:- func foldr(func(T, U) = U, cord(T), U) = U.

    % equal(CA, CB)  <=>  list(CA) = list(CB).
    % An O(n) operation where n = length(CA) + length(CB).
    %
    % (Note: the current implementation works exactly this way.)
    %
:- pred equal(cord(T)::in, cord(T)::in) is semidet.

%--------------------------------------------------%
%--------------------------------------------------%


Node:counter, Next:, Previous:cord, Up:Top

16 counter


%--------------------------------------------------%
% Copyright (C) 2000 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: counter.m.
% Author: zs.
% Stability: high.
%
% Predicates for dealing with counters, which are mechanisms for allocating
% consecutively numbered integers. The abstraction barrier eliminates the
% possibility of confusion along the lines of "does this counter record
% the next number to be handed out, or the last number that was handed out?".
%
%--------------------------------------------------%

:- module counter.

:- interface.

:- type counter.

	% counter_init(N, Counter) returns a counter whose first allocation
	% will be the integer N.
:- pred counter__init(int::in, counter::out) is det.

	% A function version of counter__init/2.
:- func counter__init(int) = counter.

	% counter__allocate(N, Counter0, Counter) takes a counter, and
	% returns (a) the next integer to be allocated from that counter,
	% and (b) the updated state of the counter.
:- pred counter__allocate(int::out, counter::in, counter::out) is det.


Node:deconstruct, Next:, Previous:counter, Up:Top

17 deconstruct


%--------------------------------------------------%
% Copyright (C) 2002-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: deconstruct.m.
% Main author: zs.
% Stability: low.

%--------------------------------------------------%
%--------------------------------------------------%

:- module deconstruct.

:- interface.

:- import_module std_util, list.

	% Values of type noncanon_handling are intended to control how
	% predicates that deconstruct terms behave when they find that
	% the term they are about to deconstruct is of a noncanonical type,
	% i.e. of a type in which a single logical value may have more than one
	% concrete representation.
	%
	% The value `do_not_allow' means that in such circumstances the
	% predicate should abort.
	%
	% The value `canonicalize' means that in such circumstances the
	% predicate should return a constant giving the identity of the type,
	% regardless of the actual value of the term.
	%
	% The value `include_details_cc' means that in such circumstances
	% the predicate should proceed as if the term were of a canonical type.
	% Use of this option requires a committed choice context.

:- type noncanon_handling
	--->	do_not_allow
	;	canonicalize
	;	include_details_cc.

:- inst do_not_allow ---> do_not_allow.
:- inst canonicalize ---> canonicalize.
:- inst include_details_cc ---> include_details_cc.
:- inst canonicalize_or_do_not_allow
	--->	do_not_allow
	;	canonicalize.

	% functor, argument and deconstruct and their variants take any type
	% (including univ), and return representation information for that type.
	%
	% The string representation of the functor that these predicates
	% return is:
	%
	% 	- for user defined types with standard equality, the functor
	%	  that is given in the type definition. For lists, this means
	%	  the functors [|]/2 and []/0 are used, even if the list uses
	%	  the [....] shorthand.
	%	- for user-defined types with user-defined equality, the
	%	  functor will be of the form <<module:type/arity>>, except
	%	  with include_details_cc, in which case the type will be
	%	  handled as if it had standard equality.
	%	- for integers, the string is a base 10 number;
	%	  positive integers have no sign.
	%	- for floats, the string is a floating point, base 10 number;
	%	  positive floating point numbers have no sign.
	%	- for strings, the string, inside double quotation marks
	%	- for characters, the character inside single quotation marks
	%	- for predicates, the string <<predicate>>, and for functions,
	%	  the string <<function>>, except with include_details_cc,
	%	  in which case it will be the predicate or function name.
	%	  (The predicate or function name will be artificial for
	%	  predicate and function values created by lambda expressions.)
	%	- for tuples, the string {}.
	%	- for arrays, the string <<array>>.
	%
	% The arity that these predicates return is:
	%
	% 	- for user defined types with standard equality, the arity
	%	  of the functor.
	% 	- for user defined types with user-defined equality, zero,
	%	  except with include_details_cc, in which case the type
	%	  will be handled as if it had standard equality.
	%	- for integers, zero.
	%	- for floats, zero.
	%	- for strings, zero.
	%	- for characters, zero.
	%	- for predicates and functions, zero, except with
	%	  include_details_cc, in which case it will be the number of
	%	  arguments hidden in the closure.
	%	- for tuples, the number of elements in the tuple.
	%	- for arrays, the number of elements in the array.
	%
	% Note that in the current University of Melbourne implementation,
	% the implementations of these predicates depart from the above
	% specification in that with --high-level-code, they do not
	% deconstruct predicate- and function-valued terms even with
	% include_details_cc; instead, they return <<predicate>> or
	% <<function>> (in both cases with arity zero) as appropriate.

	% functor(Data, NonCanon, Functor, Arity)
	%
	% Given a data item (Data), binds Functor to a string
	% representation of the functor and Arity to the arity of this
	% data item.
	%
:- pred functor(T, noncanon_handling, string, int).
:- mode functor(in, in(do_not_allow), out, out) is det.
:- mode functor(in, in(canonicalize), out, out) is det.
:- mode functor(in, in(include_details_cc), out, out) is cc_multi.
:- mode functor(in, in, out, out) is cc_multi.

	% arg(Data, NonCanon, Index, Argument)
	%
	% Given a data item (Data) and an argument index (Index), starting
	% at 0 for the first argument, binds Argument to that argument of
	% the functor of the data item. If the argument index is out of range
	% -- that is, greater than or equal to the arity of the functor or
	% lower than 0 -- then the call fails.
	%
	% Note that this predicate only returns an answer when NonCanon is
	% do_not_allow or canonicalize.  If you need the include_details_cc
	% behaviour use deconstruct__arg_cc/3.
	%
:- some [ArgT] pred arg(T, noncanon_handling, int, ArgT).
:- mode arg(in, in(do_not_allow), in, out) is semidet.
:- mode arg(in, in(canonicalize), in, out) is semidet.
:- mode arg(in, in(canonicalize_or_do_not_allow), in, out) is semidet.

	% arg_cc/3 is similar to arg/4, except that it
	% handles arguments with non-canonical types.
	% See the documentation of std_util__arg_cc.
:- pred arg_cc(T, int, std_util__maybe_arg).
:- mode arg_cc(in, in, out) is cc_multi.

	% named_arg(Data, NonCanon, Name, Argument)
	%
	% Same as arg/4, except the chosen argument is specified by giving
	% its name rather than its position. If Data has no argument with that
	% name, named_arg fails.
	%
:- some [ArgT] pred named_arg(T, noncanon_handling, string, ArgT).
:- mode named_arg(in, in(do_not_allow), in, out) is semidet.
:- mode named_arg(in, in(canonicalize), in, out) is semidet.
:- mode named_arg(in, in(canonicalize_or_do_not_allow), in, out) is semidet.

	% named_arg_cc/3 is similar to named_arg/4, except that it
	% handles arguments with non-canonical types.
:- pred named_arg_cc(T, string, std_util__maybe_arg) is cc_multi.
:- mode named_arg_cc(in, in, out) is cc_multi.

	% det_arg(Data, NonCanon, Index, Argument)
	%
	% Same as arg/4, except that for cases where
	% arg/4 would fail, det_arg/4 will abort.
	%
:- some [ArgT] pred det_arg(T, noncanon_handling, int, ArgT).
:- mode det_arg(in, in(do_not_allow), in, out) is det.
:- mode det_arg(in, in(canonicalize), in, out) is det.
:- mode det_arg(in, in(include_details_cc), in, out) is cc_multi.
:- mode det_arg(in, in, in, out) is cc_multi.

	% det_named_arg(Data, NonCanon, Name, Argument)
	%
	% Same as named_arg/4, except that for cases where
	% named_arg/4 would fail, det_named_arg/4 will abort.
	%
:- some [ArgT] pred det_named_arg(T, noncanon_handling, string, ArgT).
:- mode det_named_arg(in, in(do_not_allow), in, out) is det.
:- mode det_named_arg(in, in(canonicalize), in, out) is det.
:- mode det_named_arg(in, in(include_details_cc), in, out) is cc_multi.
:- mode det_named_arg(in, in, in, out) is cc_multi.

	% deconstruct(Data, NonCanon, Functor, Arity, Arguments)
	%
	% Given a data item (Data), binds Functor to a string
	% representation of the functor, Arity to the arity of this data
	% item, and Arguments to a list of arguments of the functor.
	% The arguments in the list are each of type univ.
	%
	% The cost of calling deconstruct depends greatly on how many arguments
	% Data has. If Data is an array, then each element of the array is
	% considered one of its arguments. Therefore calling deconstruct
	% on large arrays can take a very large amount of memory and a very
	% long time. If you call deconstruct in a situation in which you may
	% pass it a large array, you should probably use limited_deconstruct
	% instead.
	%
:- pred deconstruct(T, noncanon_handling, string, int, list(univ)).
:- mode deconstruct(in, in(do_not_allow), out, out, out) is det.
:- mode deconstruct(in, in(canonicalize), out, out, out) is det.
:- mode deconstruct(in, in(include_details_cc), out, out, out) is cc_multi.
:- mode deconstruct(in, in, out, out, out) is cc_multi.

	% limited_deconstruct(Data, NonCanon, MaxArity,
	%	Functor, Arity, Arguments)
	%
	% limited_deconstruct works like deconstruct, but if the arity of T is
	% greater than MaxArity, limited_deconstruct fails. This is useful in
	% avoiding bad performance in cases where Data may be a large array.
	%
	% Note that this predicate only returns an answer when NonCanon is
	% do_not_allow or canonicalize.  If you need the include_details_cc
	% behaviour use deconstruct__limited_deconstruct_cc/3.
	%
:- pred limited_deconstruct(T, noncanon_handling, int, string, int,
	list(univ)).
:- mode limited_deconstruct(in, in(do_not_allow), in, out, out, out)
	is semidet.
:- mode limited_deconstruct(in, in(canonicalize), in, out, out, out)
	is semidet.

	% See the documentation of std_util__limited_deconstruct_cc.
:- pred limited_deconstruct_cc(T, int, maybe({string, int, list(univ)})).
:- mode limited_deconstruct_cc(in, in, out) is cc_multi.


Node:dir, Next:, Previous:deconstruct, Up:Top

18 dir


%--------------------------------------------------%
% Copyright (C) 1994-1995,1997,1999-2000,2002-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: dir.m.
% Main authors: fjh, stayl.

% Filename and directory handling.
% Stability: high.
%
% Note that the predicates and functions in this module change
% directory separators in paths passed to them to the normal
% separator for the platform, if that doesn't change the meaning
% of the path name.
%
% Duplicate directory separators and trailing separators are also
% removed where that doesn't change the meaning of the path name.
%
%--------------------------------------------------%

:- module dir.
:- interface.

:- import_module bool.
:- import_module io.
:- import_module list.
:- import_module string.

	% predicates to isolate system dependencies

	% Returns the default separator between components of a pathname --
	% '/' on Unix systems and '\\' on Microsoft Windows systems.
:- func dir__directory_separator = character.
:- pred dir__directory_separator(character::out) is det.

	% Is the character a directory separator.
	% On Microsoft Windows systems this will succeed for '/'
	% as well as '\\'.
:- pred dir__is_directory_separator(character).
:- mode dir__is_directory_separator(in) is semidet.
:- mode dir__is_directory_separator(out) is multi.

	% Returns ".".
:- func dir__this_directory = string.
:- pred dir__this_directory(string::out) is det.

	% Returns "..".
:- func dir__parent_directory = string.
:- pred dir__parent_directory(string::out) is det.

	% dir__split_name(PathName, DirName, BaseName).
	%
	% Split a filename into a directory part and a filename part.
	%
	% Fails for root directories or relative filenames not
	% containing directory information.
	%
	% Trailing slashes are removed from PathName before splitting,
	% if that doesn't change the meaning of PathName.
	%
	% Trailing slashes are removed from DirName after splitting,
	% if that doesn't change the meaning of DirName.
	%
	% On Windows, drive current directories are handled correctly,
	% for example `dir__split_name("C:foo", "C:", "foo")'.
	% (`X:' is the current directory on drive `X').
	% Note that Cygwin doesn't support drive current directories,
	% so `dir__split_name("C:foo, _, _)' will fail when running
	% under Cygwin.
:- pred dir__split_name(string::in, string::out, string::out) is semidet.

	% dir__basename(PathName) = BaseName.
	%
	% Returns the non-directory part of a filename.
	%
	% Fails when given a root directory, ".", ".." or a Windows
	% path such as "X:".
	%
	% Trailing slashes are removed from PathName before splitting,
	% if that doesn't change the meaning of PathName.
:- func dir__basename(string) = string is semidet.
:- pred dir__basename(string::in, string::out) is semidet.

	% As above, but throw an exception instead of failing.
:- func dir__basename_det(string) = string.

	% dir__dirname(PathName) = DirName.
	%
	% Returns the directory part of a filename.
	%
	% Returns PathName if it specifies a root directory.
	%
	% Returns PathName for Windows paths such as "X:".
	%
	% Returns `dir__this_directory' when given a filename
	% without any directory information (e.g. "foo").
	%
	% Trailing slashes in PathName are removed first, if that
	% doesn't change the meaning of PathName.
	%
	% Trailing slashes are removed from DirName after splitting,
	% if that doesn't change the meaning of DirName.
:- func dir__dirname(string) = string.
:- pred dir__dirname(string::in, string::out) is det.

	% dir__path_name_is_absolute(PathName)
	%
	% Is the path name syntactically an absolute path
	% (this doesn't check whether the path exists).
	%
	% An path is absolute iff it begins with a root directory
	% (see dir__path_name_is_root_directory).
:- pred dir__path_name_is_absolute(string::in) is semidet.

	% dir__path_name_is_root_directory(PathName)
	%
	% On Unix, '/' is the only root directory.
	% On Windows, a root directory is one of the following:
	%	'X:\', which specifies the root directory of drive X,
	%		where X is any letter.
	%	'\', which specifies the root directory of the current drive.
	%	'\\server\share\', which specifies a UNC (Universal Naming
	%		Convention) root directory for a network drive.
	%
	% Note that 'X:' is not a Windows root directory -- it specifies the
	% current directory on drive X, where X is any letter.
:- pred dir__path_name_is_root_directory(string::in) is semidet.

	% PathName = DirName / FileName
	%
	% Given a directory name and a filename, return the pathname of that
	% file in that directory.
	%
	% Duplicate directory separators will not be introduced if
	% DirName ends with a directory separator.
	%
	% On Windows, a call such as `"C:"/"foo"' will return "C:foo".
	%
	% Throws an exception if FileName is an absolute path name.
	% Throws an exception on Windows if FileName is a current
	% drive relative path such as "C:".
:- func string / string = string.
:- func dir__make_path_name(string, string) = string.

%--------------------------------------------------%

	% Make the given directory, and all parent directories.
	% This will also succeed if the directory already exists
	% and is readable and writable by the current user.
:- pred dir__make_directory(string::in, io__res::out, io::di, io::uo) is det.

	% Make only the given directory.
	% Fails if the directory already exists, or the parent
	% directory doesn't.
:- pred dir__make_single_directory(string::in, io__res::out, io::di, io::uo)
	is det.

%--------------------------------------------------%

	% FoldlPred(DirName, BaseName, FileType, Continue, !Data, !IO).
	%
	% A predicate passed to dir__foldl2 to process each entry in
	% a directory.
	% Processing will stop if Continue is bound to `no'.
:- type dir__foldl_pred(T) == pred(string, string, io__file_type, bool,
					T, T, io, io).
:- inst dir__foldl_pred == (pred(in, in, in, out, in, out, di, uo) is det).

	% dir__foldl2(P, DirName, InitialData, Result, !IO).
	%
	% Apply `P' to all files and directories in the given directory.
	% Directories are not processed recursively.
	% Processing will stop if the boolean (Continue) output of P is bound
	% to `no'.
	% The order in which the entries are processed is unspecified.
:- pred dir__foldl2(dir__foldl_pred(T)::in(dir__foldl_pred), string::in,
	T::in, io__maybe_partial_res(T)::out, io::di, io::uo) is det.

	% dir__recursive_foldl2(P, DirName, FollowSymLinks,
	% 	InitialData, Result, !IO).
	%
	% As above, but recursively process subdirectories.
	% Subdirectories are processed depth-first, processing
	% the directory itself before its contents.
	% If `FollowSymLinks' is `yes', recursively process the
	% directories referenced by symbolic links.
:- pred dir__recursive_foldl2(dir__foldl_pred(T)::in(dir__foldl_pred),
	string::in, bool::in, T::in, io__maybe_partial_res(T)::out,
	io::di, io::uo) is det.

%--------------------------------------------------%

	% Implement brace expansion, as in sh: return the sequence of strings
	% generated from the given input string. Throw an exception if the
	% input string contains mismatched braces.
	%
	% The following is the documentation of brace expansion from the sh
	% manual:
	%
	%	Brace expansion is a mechanism by which arbitrary strings may
	%	be generated. This mechanism is similar to pathname expansion,
	%	but the filenames generated need not exist. Patterns to be
	%	brace expanded take the form of an optional preamble, followed
	%	by a series of comma-separated strings between a pair of
	%	braces, followed by an optional postscript. The preamble is
	%	prefixed to each string contained within the braces, and the
	%	postscript is then appended to each resulting string, expanding
	%	left to right.
	%
	%	Brace expansions may be nested. The results of each expanded
	%	string are not sorted; left to right order is preserved.
	%	For example, a{d,c,b}e expands into `ade ace abe'.
:- func expand_braces(string) = list(string).

%--------------------------------------------------%


Node:enum, Next:, Previous:dir, Up:Top

19 enum


%--------------------------------------------------%
% Copyright (C) 2000 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: enum.m.
% Author: stayl.
% Stability: very low.
%
% This module provides the typeclass `enum', which describes
% types which can be converted to and from integers without loss
% of information.
%
% The interface of this module is likely to change.
% At the moment it is probably best to only use the `enum'
% type class for types to be stored in `sparse_bitset's.
%
%--------------------------------------------------%

:- module enum.

:- interface.

	% For all instances the following must hold:
	%	all [X, Int] (X = from_int(to_int(X)))
:- typeclass enum(T) where [
	func to_int(T) = int,
	func from_int(int) = T is semidet
].

%--------------------------------------------------%


Node:eqvclass, Next:, Previous:enum, Up:Top

20 eqvclass


%--------------------------------------------------%
% Copyright (C) 1995-1997, 1999, 2003 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: eqvclass.m.
% Author: zs.
% Stability: low.
%
% A module for handling equivalence classes.
%
%--------------------------------------------------%

:- module eqvclass.

:- interface.

:- import_module set, list.

:- type eqvclass(T).

	% Create an empty equivalance class.

:- pred eqvclass__init(eqvclass(T)).
:- mode eqvclass__init(out) is det.

:- func eqvclass__init = eqvclass(T).

	% Is this item known to the equivalence class?

:- pred eqvclass__is_member(eqvclass(T), T).
:- mode eqvclass__is_member(in, in) is semidet.

	% Make an element known to the equivalence class.
	% The element may already be known to the class;
	% if it isn't, it is created without any equivalence relationships.

:- pred eqvclass__ensure_element(eqvclass(T), T, eqvclass(T)).
:- mode eqvclass__ensure_element(in, in, out) is det.

:- func eqvclass__ensure_element(eqvclass(T), T) = eqvclass(T).

	% Make an element known to the equivalence class.
	% The element must not already be known to the class;
	% it is created without any equivalence relationships.

:- pred eqvclass__new_element(eqvclass(T), T, eqvclass(T)).
:- mode eqvclass__new_element(in, in, out) is det.

:- func eqvclass__new_element(eqvclass(T), T) = eqvclass(T).

	% Make two elements of the equivalence class equivalent.
	% It is ok if they already are.

:- pred eqvclass__ensure_equivalence(eqvclass(T), T, T, eqvclass(T)).
:- mode eqvclass__ensure_equivalence(in, in, in, out) is det.

:- func eqvclass__ensure_equivalence(eqvclass(T), T, T) = eqvclass(T).

	% Make two elements of the equivalence class equivalent.
	% It is an error if they are already equivalent.

:- pred eqvclass__new_equivalence(eqvclass(T), T, T, eqvclass(T)).
:- mode eqvclass__new_equivalence(in, in, in, out) is det.

:- func eqvclass__new_equivalence(eqvclass(T), T, T) = eqvclass(T).

	% Test if two elements are equivalent.

:- pred eqvclass__same_eqvclass(eqvclass(T), T, T).
:- mode eqvclass__same_eqvclass(in, in, in) is semidet.

	% Test if a list of elements are equivalent.

:- pred eqvclass__same_eqvclass_list(eqvclass(T), list(T)).
:- mode eqvclass__same_eqvclass_list(in, in) is semidet.

	% Return the set of the partitions of the equivalence class.

:- pred eqvclass__partition_set(eqvclass(T), set(set(T))).
:- mode eqvclass__partition_set(in, out) is det.

:- func eqvclass__partition_set(eqvclass(T)) = set(set(T)).

	% Return a list of the partitions of the equivalence class.

:- pred eqvclass__partition_list(eqvclass(T), list(set(T))).
:- mode eqvclass__partition_list(in, out) is det.

:- func eqvclass__partition_list(eqvclass(T)) = list(set(T)).

	% Create an equivalence class from a partition set.
	% It is an error if the sets are not disjoint.

:- pred eqvclass__partition_set_to_eqvclass(set(set(T)), eqvclass(T)).
:- mode eqvclass__partition_set_to_eqvclass(in, out) is det.

:- func eqvclass__partition_set_to_eqvclass(set(set(T))) = eqvclass(T).

	% Create an equivalence class from a list of partitions.
	% It is an error if the sets are not disjoint.

:- pred eqvclass__partition_list_to_eqvclass(list(set(T)), eqvclass(T)).
:- mode eqvclass__partition_list_to_eqvclass(in, out) is det.

:- func eqvclass__partition_list_to_eqvclass(list(set(T))) = eqvclass(T).

%--------------------------------------------------%


Node:exception, Next:, Previous:eqvclass, Up:Top

21 exception


%--------------------------------------------------%
% Copyright (C) 1997-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: exception.m.
% Main author: fjh.
% Stability: medium

% This file defines the Mercury interface for exception handling.

% Note that throwing an exception across the C interface won't work.
% That is, if a Mercury procedure that is exported to C using `pragma export'
% throws an exception which is not caught within that procedure, then
% you will get undefined behaviour.

%--------------------------------------------------%
%--------------------------------------------------%
:- module exception.
:- interface.
:- import_module std_util, list, io, store.

%
% throw(Exception):
%	Throw the specified exception.
%
:- pred throw(T).
:- mode throw(in) is erroneous.

:- func throw(T) = _.
:- mode throw(in) = out is erroneous.

% The following types are used by try/3 and try/5.

:- type exception_result(T)
	--->	succeeded(T)
	;	failed
	;	exception(univ).

:- inst cannot_fail
	--->	succeeded(ground)
	;	exception(ground).

%
% try(Goal, Result):
%    Operational semantics:
%	Call Goal(R).
%	If Goal(R) fails, succeed with Result = failed.
%	If Goal(R) succeeds, succeed with Result = succeeded(R).
%	If Goal(R) throws an exception E, succeed with Result = exception(E).
%    Declarative semantics:
%       try(Goal, Result) <=>
%               ( Goal(R), Result = succeeded(R)
%               ; not Goal(_), Result = failed
%               ; Result = exception(_)
%		).
%
:- pred try(pred(T),		    exception_result(T)).
:- mode try(pred(out) is det,       out(cannot_fail)) is cc_multi.
:- mode try(pred(out) is semidet,   out)              is cc_multi.
:- mode try(pred(out) is cc_multi,  out(cannot_fail)) is cc_multi.
:- mode try(pred(out) is cc_nondet, out)              is cc_multi.

%
% try_io(Goal, Result, IO_0, IO):
%    Operational semantics:
%	Call Goal(R, IO_0, IO_1).
%	If it succeeds, succeed with Result = succeeded(R) and IO = IO_1.
%	If it throws an exception E, succeed with Result = exception(E)
%	and with the final IO state being whatever state resulted
%	from the partial computation from IO_0.
%    Declarative semantics:
%	try_io(Goal, Result, IO_0, IO) <=>
%		( Goal(R, IO_0, IO), Result = succeeded(R)
%		; Result = exception(_)
%		).
%
:- pred try_io(pred(T, io, io),
	exception_result(T), io, io).
:- mode try_io(pred(out, di, uo) is det,
	out(cannot_fail), di, uo) is cc_multi.
:- mode try_io(pred(out, di, uo) is cc_multi,
	out(cannot_fail), di, uo) is cc_multi.

%
% try_store(Goal, Result, Store_0, Store):
%    Just like try_io, but for stores rather than io__states.
%
:- pred try_store(pred(T, store(S), store(S)),
	exception_result(T), store(S), store(S)).
:- mode try_store(pred(out, di, uo) is det,
	out(cannot_fail), di, uo) is cc_multi.
:- mode try_store(pred(out, di, uo) is cc_multi,
	out(cannot_fail), di, uo) is cc_multi.

%
% try_all(Goal, ResultList):
%    Operational semantics:
%	Try to find all solutions to Goal(R), using backtracking.
%	Collect the solutions found in the ResultList, until
%	the goal either throws an exception or fails.
%	If it throws an exception, put that exception at the end of
%	the ResultList.
%    Declaratively:
%       try_all(Goal, ResultList) <=>
%		(if
%			list__reverse(ResultList, [Last | AllButLast]),
%			Last = exception(_)
%		then
%			all [M] (list__member(M, AllButLast) =>
%				(M = succeeded(R), Goal(R))),
%		else
%			all [M] (list__member(M, ResultList) =>
%				(M = succeeded(R), Goal(R))),
%			all [R] (Goal(R) =>
%				list__member(succeeded(R), ResultList)),
%		).

:- pred try_all(pred(T), list(exception_result(T))).
:- mode try_all(pred(out) is det,     out(try_all_det))     is cc_multi.
:- mode try_all(pred(out) is semidet, out(try_all_semidet)) is cc_multi.
:- mode try_all(pred(out) is multi,   out(try_all_multi))   is cc_multi.
:- mode try_all(pred(out) is nondet,  out(try_all_nondet))  is cc_multi.

:- inst [] ---> [].
:- inst try_all_det ---> [cannot_fail].
:- inst try_all_semidet ---> [] ; [cannot_fail].
:- inst try_all_multi ---> [cannot_fail | try_all_nondet].
:- inst try_all_nondet == list_skel(cannot_fail).

%
% incremental_try_all(Goal, AccumulatorPred, Acc0, Acc):
%    Same as
%	try_all(Goal, Results),
%	std_util__unsorted_aggregate(Results, AccumulatorPred, Acc0, Acc)
%    except that operationally, the execution of try_all
%    and std_util__unsorted_aggregate is interleaved.

:- pred incremental_try_all(pred(T), pred(exception_result(T), A, A), A, A).
:- mode incremental_try_all(pred(out) is nondet,
	pred(in, di, uo) is det, di, uo) is cc_multi.
:- mode incremental_try_all(pred(out) is nondet,
	pred(in, in, out) is det, in, out) is cc_multi.

%
% rethrow(ExceptionResult):
%	Rethrows the specified exception result
%	(which should be of the form `exception(_)',
%	not `succeeded(_)' or `failed'.).
%
:- pred rethrow(exception_result(T)).
:- mode rethrow(in(bound(exception(ground)))) is erroneous.

:- func rethrow(exception_result(T)) = _.
:- mode rethrow(in(bound(exception(ground)))) = out is erroneous.

%
% finally(P, PRes, Cleanup, CleanupRes, IO0, IO).
%	Call P and ensure that Cleanup is called afterwards,
%	no matter whether P succeeds or throws an exception.
%	PRes is bound to the output of P.
%	CleanupRes is bound to the output of Cleanup.
%	A exception thrown by P will be rethrown after Cleanup
%	is called, unless Cleanup throws an exception.
%	This predicate performs the same function as the `finally'
%	clause (`try {...} finally {...}') in languages such as Java.
:- pred finally(pred(T, io, io), T, pred(io__res, io, io), io__res, io, io).
:- mode finally(pred(out, di, uo) is det, out,
	pred(out, di, uo) is det, out, di, uo) is det.
:- mode finally(pred(out, di, uo) is cc_multi, out,
	pred(out, di, uo) is cc_multi, out, di, uo) is cc_multi.

%--------------------------------------------------%
%--------------------------------------------------%


Node:float, Next:, Previous:exception, Up:Top

22 float


%--------------------------------------------------%
% Copyright (C) 1994-1998,2001-2003 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: float.m.
% Main author: fjh.
% Stability: medium.
%
% Floating point support.
%
% Note that implementations which support IEEE floating point
% should ensure that in cases where the only valid answer is a "NaN"
% (the IEEE float representation for "not a number"), the det
% functions here will halt with a runtime error (or throw an exception)
% rather than returning a NaN.  Quiet (non-signalling) NaNs have a
% semantics which is not valid in Mercury, since they don't obey the
% axiom "all [X] X = X".
%
% XXX Unfortunately the current Mercury implementation does not
% do that on all platforms, since neither ANSI C nor POSIX provide
% any portable way of ensuring that floating point operations
% whose result is not representable will raise a signal rather
% than returning a NaN.  (Maybe C9X will help...?)
% The behaviour is correct on Linux and Digital Unix,
% but not on Solaris, for example.
%
% IEEE floating point also specifies that some functions should
% return different results for +0.0 and -0.0, but that +0.0 and -0.0
% should compare equal.  This semantics is not valid in Mercury,
% since it doesn't obey the axiom `all [F, X, Y] X = Y => F(X) = F(Y)'.
% Again, the resolution is that in Mercury, functions which would
% return different results for +0.0 and -0.0 should instead halt
% execution with a run-time error (or throw an exception).
%
% XXX Here too the current Mercury implementation does not
% implement the intended semantics correctly on all platforms.
%
% XXX On machines such as x86 which support extra precision
% for intermediate results, the results may depend on the
% level of optimization, in particular inlining and evaluation
% of constant expressions.
% For example, the goal `1.0/9.0 = std_util__id(1.0)/9.0' may fail.

%--------------------------------------------------%

:- module float.
:- interface.

%
% Arithmetic functions
%

	% addition
:- func float + float = float.
:- mode in    + in    = uo  is det.

	% subtraction
:- func float - float = float.
:- mode in    - in    = uo  is det.

	% multiplication
:- func float * float = float.
:- mode in    * in    = uo  is det.

	% division
	% Throws a `math__domain_error' exception if the right
	% operand is zero. See the comments at the top of math.m
	% to find out how to disable this check.
:- func float / float = float.
:- mode in    / in    = uo  is det.

	% unchecked_quotient(X, Y) is the same as X / Y, but the
	% behaviour is undefined if the right operand is zero.
:- func unchecked_quotient(float, float) = float.
:- mode unchecked_quotient(in, in)    = uo  is det.

	% unary plus
:- func + float = float.
:- mode + in    = uo  is det.

	% unary minus
:- func - float = float.
:- mode - in    = uo  is det.

%
% Comparison predicates
%

	% less than
:- pred <(float, float).
:- mode <(in, in) is semidet.

	% greater than
:- pred >(float, float).
:- mode >(in, in) is semidet.

	% less than or equal
:- pred =<(float, float).
:- mode =<(in, in) is semidet.

	% greater than or equal
:- pred >=(float, float).
:- mode >=(in, in) is semidet.

%
% Conversion functions
%

	% Convert int to float
:- func float(int) = float.

	% ceiling_to_int(X) returns the
	% smallest integer not less than X.
:- func ceiling_to_int(float) = int.

	% floor_to_int(X) returns the
	% largest integer not greater than X.
:- func floor_to_int(float) = int.

	% round_to_int(X) returns the integer closest to X.
	% If X has a fractional value of 0.5, it is rounded up.
:- func round_to_int(float) = int.

	% truncate_to_int(X) returns
	% the integer closest to X such that |truncate_to_int(X)| =< |X|.
:- func truncate_to_int(float) = int.

%
% Miscellaneous functions
%

	% absolute value
:- func abs(float) = float.

	% maximum
:- func max(float, float) = float.

	% minimum
:- func min(float, float) = float.

	% pow(Base, Exponent) returns Base raised to the power Exponent.
	% Fewer domain restrictions than math__pow: works for negative Base,
	% and float__pow(B, 0) = 1.0 for all B, even B=0.0.
	% Only pow(0, <negative>) throws a `math__domain_error' exception.
:- func pow(float, int) = float.

	% Compute a non-negative integer hash value for a float.
:- func hash(float) = int.

	% Is the float point number not a number or infinite?
:- pred is_nan_or_inf(float::in) is semidet.

	% Is the floating point number not a number?
:- pred is_nan(float::in) is semidet.

	% Is the floating point number infinite?
:- pred is_inf(float::in) is semidet.

%
% System constants
%

	% Maximum finite floating-point number
	%
	% max = (1 - radix ** mantissa_digits) * radix ** max_exponent
	%
:- func float__max = float.

	% Minimum normalised positive floating-point number
	%
	% min = radix ** (min_exponent - 1)
	%
:- func float__min = float.

	% Smallest number x such that 1.0 + x \= 1.0
	% This represents the largest relative spacing of two
	% consecutive floating point numbers.
	%
	% epsilon = radix ** (1 - mantissa_digits)
:- func float__epsilon = float.

	% Radix of the floating-point representation.
	% In the literature, this is sometimes referred to as `b'.
	%
:- func float__radix = int.

	% The number of base-radix digits in the mantissa.  In the
	% literature, this is sometimes referred to as `p' or `t'.
	%
:- func float__mantissa_digits = int.

	% Minimum negative integer such that:
	%	radix ** (min_exponent - 1)
	% is a normalised floating-point number.  In the literature,
	% this is sometimes referred to as `e_min'.
	%
:- func float__min_exponent = int.

	% Maximum integer such that:
	%	radix ** (max_exponent - 1)
	% is a normalised floating-point number.  In the literature,
	% this is sometimes referred to as `e_max'.
	%
:- func float__max_exponent = int.

%--------------------------------------------------%
%--------------------------------------------------%


Node:gc, Next:, Previous:float, Up:Top

23 gc


%--------------------------------------------------%
% Copyright (C) 1999,2001-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: gc.m.
% Author: fjh.
% Stability: medium.
%
% This module defines some procedures for controlling the actions
% of the garbage collector.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module gc.
:- interface.
:- import_module io.

	% Force a garbage collection.
:- pred garbage_collect(io__state::di, io__state::uo) is det.

	% Force a garbage collection.
	% Note that this version is not really impure, but it needs to be
	% declared impure to ensure that the compiler won't try to
	% optimize it away.
:- impure pred garbage_collect is det.

%--------------------------------------------------%


Node:getopt, Next:, Previous:gc, Up:Top

24 getopt


%--------------------------------------------------%
% Copyright (C) 1994-1999,2001-2003 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING in the Mercury distribution.
%--------------------------------------------------%

% File: getopt.m
% Authors: fjh, zs
% Stability: medium

% This module exports the predicate getopt__process_options/4,
% which can be used to parse command-line options.
%
% This version allows both short (single-character) options
% and GNU-style long options. It also has the GNU extension
% of recognizing options anywhere in the command-line, not
% just at the start.
%
% To use this module, you must provide an `option' type which
% is an enumeration of all your different options.
% You must provide predicates `short_option(Char, Option)'
% and `long_option(String, Option)' which convert the short
% and/or long names for the option to this enumeration type.
% (An option can have as many names as you like, long or short.)
% You must provide a predicate `option_default(Option, OptionData)'
% which specifies both the type and the default value for every option.
% You may optionally provide a predicate `special_handler(Option,
% SpecialData, OptionTable, MaybeOptionTable)' for handling special
% option types.  (See below.)
%
% We support the following "simple" option types:
%
%	- bool
%	- int
%	- maybe_int (which have a value of `no' or `yes(int)')
%	- string
%	- maybe_string (which have a value of `no' or `yes(string)')
%
% We also support one "accumulating" option type:
%
%	- accumulating (which accumulates a list of strings)
%
% And the following "special" option types:
%
%	- special
%	- bool_special
%	- int_special
%	- string_special
%	- maybe_string_special
%
% For the "simple" option types, if there are multiple occurrences
% of the same option on the command-line, then the last (right-most)
% occurrence will take precedence.  For "accumulating" options,
% multiple occurrences will be appended together into a list.
%
% The "special" option types are handled by a special option handler
% (see `special_handler' below), which may perform arbitrary
% modifications to the option_table.  For example, an option which
% is not yet implemented could be handled by a special handler which
% produces an error report, or an option which is a synonym for a
% set of more "primitive" options could be handled by a special
% handler which sets those "primitive" options.
%
% It is an error to use a "special" option for which there is no
% handler, or for which the handler fails.
%
% Boolean (i.e. bool or bool_special), maybe_int, maybe_string
% and accumulating options can be negated. Negating an accumulating
% option empties the accumulated list of strings.
% Single-character options can be negated by following them
% with another `-', e.g. `-x-' will negate the `-x' option.
% Long options can be negated by preceding them with `--no-',
% e.g. `--no-foo' will negate the `--foo' option.

:- module getopt.
:- interface.
:- import_module bool, char, list, map, std_util.

% getopt__process_options(OptionOps, Args, NonOptionArgs, Result)
%
% getopt__process_options(OptionOps, Args, OptionArgs, NonOptionArgs, Result)
%
%	Scans through 'Args' looking for options, places all the option
%	arguments in `OptionArgs', places all the non-option arguments in
%	'NonOptionArgs', and records the options in the `OptionTable'.
%	`OptionTable' is a map from a user-defined option type to option_data.
%	If an invalid option is encountered, we return `error(Message)'
%	otherwise we return `ok(OptionTable)' in 'Result'.
%
%	The argument `OptionOps' is a structure holding three or four
%	predicates used to categorize a set of options. Their
%	interfaces should be like these:
%
% :- pred short_option(char::in, option::out) is semidet.
% 	True if the character names a valid single-character option.
%
% :- pred long_option(string::in, option::out) is semidet.
%	True if the character names a valid long option.
%
% :- pred option_default(option::out, option_data::out) is nondet.
%	Nondeterministically returns all the options with their
%	corresponding types and default values.
%
% :- pred special_handler(option::in, special_data::in,
%	option_table::in, maybe_option_table(_)::out) is semidet.
%	This predicate is invoked whenever getopt finds an option
%	(long or short) designated as special, with special_data holding
%	the argument of the option (if any). The predicate can change the
%	option table in arbitrary ways in the course of handling the option,
%	or it can return an error message.
%	The canonical examples of special options are -O options in compilers,
%	which set many other options at once.

:- pred getopt__process_options(
		option_ops(OptionType)::in(option_ops),
		list(string)::in,
		list(string)::out,
		maybe_option_table(OptionType)::out
	) is det.

:- pred getopt__process_options(
		option_ops(OptionType)::in(option_ops),
		list(string)::in,
		list(string)::out,
		list(string)::out,
		maybe_option_table(OptionType)::out
	) is det.

:- type option_ops(OptionType)
	--->	option_ops(
			pred(char, OptionType),		% short_option
			pred(string, OptionType),	% long_option
			pred(OptionType, option_data)	% option_default
		)
	;	option_ops(
			pred(char, OptionType),		% short_option
			pred(string, OptionType),	% long_option
			pred(OptionType, option_data),	% option_default
			pred(OptionType, special_data,	% special option handler
				option_table(OptionType),
				maybe_option_table(OptionType))
		).

:- inst option_ops =
	bound((
		option_ops(
			pred(in, out) is semidet,	% short_option
			pred(in, out) is semidet,	% long_option
			pred(out, out) is nondet	% option_default
		)
	;	option_ops(
			pred(in, out) is semidet,	% short_option
			pred(in, out) is semidet,	% long_option
			pred(out, out) is nondet,	% option_default
			pred(in, in, in, out) is semidet% special handler
		)
	)).

:- type option_data
	--->	bool(bool)
	;	int(int)
	;	string(string)
	;	maybe_int(maybe(int))
	;	maybe_string(maybe(string))
	;	accumulating(list(string))
	;	special
	;	bool_special
	;	int_special
	;	string_special
	;	maybe_string_special.

:- type special_data
	--->	none
	;	bool(bool)
	;	int(int)
	;	string(string)
	;	maybe_string(maybe(string)).

:- type option_table(OptionType)
	==	map(OptionType, option_data).

:- type maybe_option_table(OptionType)
	--->	ok(option_table(OptionType))
	;	error(string).

	% The following three predicates search the option table for
	% an option of the specified type; if it is not found, they
	% report an error by calling error/1.

:- pred getopt__lookup_bool_option(option_table(Option), Option, bool).
:- mode getopt__lookup_bool_option(in, in, out) is det.

:- func getopt__lookup_bool_option(option_table(Option), Option) = bool.

:- pred getopt__lookup_int_option(option_table(Option), Option, int).
:- mode getopt__lookup_int_option(in, in, out) is det.

:- func getopt__lookup_int_option(option_table(Option), Option) = int.

:- pred getopt__lookup_string_option(option_table(Option), Option, string).
:- mode getopt__lookup_string_option(in, in, out) is det.

:- func getopt__lookup_string_option(option_table(Option), Option) = string.

:- pred getopt__lookup_maybe_int_option(option_table(Option), Option,
		maybe(int)).
:- mode getopt__lookup_maybe_int_option(in, in, out) is det.

:- func getopt__lookup_maybe_int_option(option_table(Option), Option) =
		maybe(int).

:- pred getopt__lookup_maybe_string_option(option_table(Option), Option,
		maybe(string)).
:- mode getopt__lookup_maybe_string_option(in, in, out) is det.

:- func getopt__lookup_maybe_string_option(option_table(Option), Option) =
		maybe(string).

:- pred getopt__lookup_accumulating_option(option_table(Option), Option,
		list(string)).
:- mode getopt__lookup_accumulating_option(in, in, out) is det.

:- func getopt__lookup_accumulating_option(option_table(Option), Option) =
		list(string).

%--------------------------------------------------%


Node:graph, Next:, Previous:getopt, Up:Top

25 graph


%--------------------------------------------------%
% Copyright (C) 1994-1999, 2003 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: graph.m.
% Main author: conway.
% Stability: low.
%
% This module defines a directed graph data type. The type graph(N, A)
% stores information of type N in the nodes, and information of type A
% in the arcs.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module graph.

:- interface.
:- import_module list, set, std_util.

	% graph(Node, Arc) represents a directed graph with information of
	% type Node associated with each node, and information of type Arc
	% associated with each arc.
:- type graph(N, A).

:- type node(N).

:- type arc(A).

	% Lots of graphs don't need to store anything in the arcs so here's
	% a type equivalence that only has `real' information in the nodes.
:- type graph(N)	== graph(N, unit).

:- type arc		== arc(unit).

	% graph__init(Graph) binds Graph to an empty graph
	% containing no nodes and no arcs. (The graph contains
	% a counter of the number of nodes allocated in it, so
	% it is possible for a graph to contain no nodes or arcs
	% and still fail to unify with the binding of Graph from
	% graph__init.)
:- pred graph__init(graph(N, A)).
:- mode graph__init(out) is det.

:- func graph__init = graph(N, A).

	% graph__set_node(OldGraph, NodeInfo, Node, NewGraph) takes
	% OldGraph and NodeInfo which is the information to be stored
	% in a new node, and returns a key "Node" which refers to that
	% node, and the new graph NewGraph containing all of the nodes
	% and arcs in OldGraph as well as the new node.
	% It is possible to have two nodes in the graph with the
	% same information stored in them.
	%
	% This operation is O(lgN) for a graph containing N nodes.
:- pred graph__set_node(graph(N, A), N, node(N), graph(N, A)).
:- mode graph__set_node(in, in, out, out) is det.

	% graph__insert_node/4 is the same as graph__set_node/4 except
	% that if the information to be stored in the node is stored
	% in another node, then the graph__insert_node/4 fails.
	%
	% This operation is O(N) for a graph containing N nodes since
	% this predicate has to check that the node data isn't in an
	% existing node.
:- pred graph__insert_node(graph(N, A), N, node(N), graph(N, A)).
:- mode graph__insert_node(in, in, out, out) is semidet.

	% graph__det_insert_node/4 is like graph__insert_node, except
	% that if the insertion would fail, it calls error/1.
:- pred graph__det_insert_node(graph(N, A), N, node(N), graph(N, A)).
:- mode graph__det_insert_node(in, in, out, out) is det.

	% graph__search_node(Graph, NodeInfo, Node) nondeterministically
	% produces bindings of Node such that Node is a node in Graph
	% that has the information NodeInfo attatched to it.
	%
	% This operation is O(lgN) for the first solution for a graph
	% containing N nodes.
:- pred graph__search_node(graph(N, A), N, node(N)).
:- mode graph__search_node(in, in, out) is nondet.

	% graph__find_matching_nodes(Graph, NodeInfo, Nodes) takes a graph
	% Graph and the information NodeInfo and returns the set of nodes
	% Nodes which have the information NodeInfo stored in them. (The set
	% Nodes will of course be empty if there are no matching nodes.)
	%
	% This operation is O(NlgN) for a graph containing N nodes.
:- pred graph__find_matching_nodes(graph(N, A), N, set(node(N))).
:- mode graph__find_matching_nodes(in, in, out) is det.

:- func graph__find_matching_nodes(graph(N, A), N) = set(node(N)).

	% graph__node_contents(Graph, Node, NodeInfo) takes Graph and
	% Node and returns the information NodeInfo stored in Node.
	%
	% This operation is O(lgN) for a graph containing N nodes.
:- pred graph__node_contents(graph(N, A), node(N), N).
:- mode graph__node_contents(in, in, out) is det.

:- func graph__node_contents(graph(N, A), node(N)) = N.

	% graph__successors(Graph, Node, Nodes) takes a graph Graph and
	% a node Node and returns the set of nodes Nodes that are reachable
	% (directly - not transitively) from Node.
	%
	% This operation is O(NlgN) for a graph containing N nodes.
:- pred graph__successors(graph(N, A), node(N), set(node(N))).
:- mode graph__successors(in, in, out) is det.

:- func graph__successors(graph(N, A), node(N)) = set(node(N)).

	% graph__nodes(Graph, Nodes) binds Nodes to the set of nodes in Graph.
:- pred graph__nodes(graph(N, A), set(node(N))).
:- mode graph__nodes(in, out) is det.

:- func graph__nodes(graph(N, A)) = set(node(N)).

	% graph__set_edge(OldGraph, Start, End, ArcInfo, Arc, NewGraph)
	% takes a graph OldGraph and adds an arc from Start to End with
	% the information ArcInfo stored in it, and returns a key for
	% that arc Arc, and the new graph NewGraph.
	% If an identical arc already exists then this operation has
	% no effect.
	%
	% This operation is O(lgN+lgM) for a graph with N nodes and M arcs.
:- pred graph__set_edge(graph(N, A), node(N), node(N), A,
						arc(A), graph(N, A)).
:- mode graph__set_edge(in, in, in, in, out, out) is det.

	% graph__insert_edge/6 is the same as graph__set_edge/6 except that
	% if an identical arc already exists in the graph the operation fails.
	% This is O(N) for a graph with N edges between the two nodes.
:- pred graph__insert_edge(graph(N, A), node(N), node(N), A,
						arc(A), graph(N, A)).
:- mode graph__insert_edge(in, in, in, in, out, out) is semidet.

	% graph__det_insert_edge/6 is like graph__insert_edge except
	% than instead of failing, it calls error/1.
:- pred graph__det_insert_edge(graph(N, A), node(N), node(N), A,
						arc(A), graph(N, A)).
:- mode graph__det_insert_edge(in, in, in, in, out, out) is det.

	% graph__arc_contents(Graph, Arc, Start, End, ArcInfo) takes a
	% graph Graph and an arc Arc and returns the start and end nodes
	% and the information stored in that arc.
:- pred graph__arc_contents(graph(N, A), arc(A), node(N), node(N), A).
:- mode graph__arc_contents(in, in, out, out, out) is det.

	% graph__path(Graph, Start, End, Path) is true iff there is a path
	% from the node Start to the node End in Graph that goes through
	% the sequence of arcs Arcs.
	% The algorithm will return paths containing at most one cycle.
:- pred graph__path(graph(N, A), node(N), node(N), list(arc(A))).
:- mode graph__path(in, in, in, out) is nondet.
:- mode graph__path(in, in, out, out) is nondet.

%--------------------------------------------------%


Node:group, Next:, Previous:graph, Up:Top

26 group


%--------------------------------------------------%
% Copyright (C) 1994-1997, 1999, 2003 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: group.m.
% main author: conway.
% stability: low.
%
% This module is probably not terribly useful, and it may not be supported
% in future releases.
%
% The `group' module provides a facility for handling a partitioned set.
% A group is a set of sets of elements, where each element is unique within
% the scope of the group. The module provides moderately efficient ways for
% manipulating groups and elements.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module group.

:- interface.

:- import_module set, list, assoc_list.

:- type group(T).

:- type group__key.

	% Create an empty group

:- pred group__init(group(T)).
:- mode group__init(out) is det.

:- func group__init = group(T).

	% Insert a set of elements into the group.

:- pred group__insert(group(T), set(T), group(T)).
:- mode group__insert(in, in, out) is det.

:- func group__insert(group(T), set(T)) = group(T).

	% Given an element, get the set containing that element.

:- pred group__group(group(T), T, set(T)).
:- mode group__group(in, in, out) is det.

:- func group__group(group(T), T) = set(T).

	% Convert the group to a set of sets.

:- pred group__to_set(group(T), set(set(T))).
:- mode group__to_set(in, out) is det.

:- func group__to_set(group(T)) = set(set(T)).

:- pred group__sets_and_keys(group(T), assoc_list(set(T), group__key)).
:- mode group__sets_and_keys(in, out) is det.

:- func group__sets_and_keys(group(T)) = assoc_list(set(T), group__key).

	% Given an element, get the key for the group containing
	% that element.

:- pred group__group_key(group(T), T, group__key).
:- mode group__group_key(in, in, out) is det.

:- func group__group_key(group(T), T) = group__key.

	% Given a group key, get the corresponding set of elements.

:- pred group__key_group(group(T), group__key, set(T)).
:- mode group__key_group(in, in, out) is det.

:- func group__key_group(group(T), group__key) = set(T).

	% Remove a set from the group, and return the set.

:- pred group__remove_group(group(T), group__key, set(T), group(T)).
:- mode group__remove_group(in, in, out, out) is det.

	% Test to see if two elements are in the same set.

:- pred group__same_group(group(T), T, T).
:- mode group__same_group(in, in, in) is semidet.

:- pred group__largest_group_key(group(T), group__key).
:- mode group__largest_group_key(in, out) is det.

:- func group__largest_group_key(group(T)) = group__key.

:- pred group__group_keys(group(T), list(group__key)).
:- mode group__group_keys(in, out) is det.

:- func group__group_keys(group(T)) = list(group__key).

%--------------------------------------------------%
%--------------------------------------------------%


Node:hash_table, Next:, Previous:group, Up:Top

27 hash_table


%--------------------------------------------------%
% vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
%--------------------------------------------------%
% Copyright (C) 2001, 2003-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: hash_table.m
% Main author: rafe
% Stability: low
%
% Hash table implementation.
%
% This implementation uses double hashing and requires the user to
% supply a predicate that will compute two independent hash values
% for any given key.
%
% Default double-hash functions are provided for ints, strings and
% generic values.
%
% The number of buckets in the hash table is always a power of 2.
%
% When a user set occupancy level is achieved, the number of buckets
% in the table is doubled and the previous contents reinserted into
% the new hash table.
%
% CAVEAT: the user is referred to the warning at the head of array.m
% with regard to the current use of unique objects.  Briefly, the
% problem is that the compiler does not yet properly understand
% unique modes, hence we fake it using non-unique modes.
% This means that care must be taken not to use an old version of a
% destructively updated structure (such as a hash_table) since the
% compiler will not currently detect such errors.
%
%--------------------------------------------------%

:- module hash_table.

:- interface.

:- import_module int, assoc_list, float, string, array, bitmap, char.

:- type hash_table(K, V).

    % XXX This is all fake until the compiler can handle nested unique modes.
    %
:- inst hash_table ==
            bound(ht(ground, ground, ground, hash_pred, bitmap, array, array)).
:- mode hash_table_ui == in(hash_table).
:- mode hash_table_di == di(hash_table).
:- mode hash_table_uo == out(hash_table).

:- type hash_pred(K) == ( pred(K, int, int) ).
:- inst hash_pred    == ( pred(in, out, out) is det ).

    % new(HashPred, N, MaxOccupancy)
    % constructs a new hash table with initial size 2 ^ N that is
    % doubled whenever MaxOccupancy is achieved; elements are
    % indexed using HashPred.
    %
    % HashPred must compute two *independent* hashes for a given
    % key - that is, one hash should not be a function of the other.
    % Otherwise poor performance will result.
    %
    % N must be greater than 1.
    % MaxOccupancy must be in (0.0, 1.0).
    %
    % XXX Values too close to the limits may cause bad things
    % to happen.
    %
:- func new(hash_pred(K), int, float) = hash_table(K, V).
:- mode new(in(hash_pred), in, in) = hash_table_uo is det.

    % new_default(HashFn) constructs a hash table with default size and
    % occupancy arguments.
    %
:- func new_default(hash_pred(K)) = hash_table(K, V).
:- mode new_default(in(hash_pred)) = hash_table_uo is det.

    % Retrieve the hash_pred associated with a hash table.
    %
:- func hash_pred(hash_table(K, V)) = hash_pred(K).
:- mode hash_pred(hash_table_ui) = out(hash_pred) is det.

    % Default hash_preds for ints and strings and everything (buwahahaha!)
    %
:- pred int_double_hash(int, int, int).
:- mode int_double_hash(in, out, out) is det.

:- pred string_double_hash(string, int, int).
:- mode string_double_hash(in, out, out) is det.

:- pred char_double_hash(char, int, int).
:- mode char_double_hash(in, out, out) is det.

:- pred float_double_hash(float, int, int).
:- mode float_double_hash(in, out, out) is det.

:- pred generic_double_hash(T, int, int).
:- mode generic_double_hash(in, out, out) is det.

    % Returns the number of buckets in a hash table.
    %
:- func num_buckets(hash_table(K, V)) = int.
:- mode num_buckets(hash_table_ui) = out is det.
%:- mode num_buckets(in) = out is det.

    % Returns the number of occupants in a hash table.
    %
:- func num_occupants(hash_table(K, V)) = int.
:- mode num_occupants(hash_table_ui) = out is det.
%:- mode num_occupants(in) = out is det.

    % Insert key-value binding into a hash table; if one is
    % already there then the previous value is overwritten.
    %
:- func set(hash_table(K, V), K, V) = hash_table(K, V).
:- mode set(hash_table_di, in, in) = hash_table_uo is det.

    % Field update for hash tables.
    % HT ^ elem(K) := V  is equivalent to  set(HT, K, V).
    %
:- func 'elem :='(K, hash_table(K, V), V) = hash_table(K, V).
:- mode 'elem :='(in, hash_table_di, in) = hash_table_uo is det.

    % Insert a key-value binding into a hash table.  An
    % exception is thrown if a binding for the key is already
    % present.
    %
:- func det_insert(hash_table(K, V), K, V) = hash_table(K, V).
:- mode det_insert(hash_table_di, in, in) = hash_table_uo is det.

    % Change a key-value binding in a hash table.  An
    % exception is thrown if a binding for the key does not
    % already exist.
    %
:- func det_update(hash_table(K, V), K, V) = hash_table(K, V).
:- mode det_update(hash_table_di, in, in) = hash_table_uo is det.

    % Delete the entry for the given key, leaving the hash table
    % unchanged if there is no such entry.
    %
:- func delete(hash_table(K, V), K) = hash_table(K, V).
:- mode delete(hash_table_di, in) = hash_table_uo is det.

    % Lookup the value associated with the given key.  An exception
    % is raised if there is no entry for the key.
    %
:- func lookup(hash_table(K, V), K) = V.
:- mode lookup(hash_table_ui, in) = out is det.
%:- mode lookup(in, in) = out is det.

    % Field access for hash tables.
    % HT ^ elem(K)  is equivalent to  lookup(HT, K).
    %
:- func elem(K, hash_table(K, V)) = V.
:- mode elem(in, hash_table_ui) = out is det.
%:- mode elem(in, in) = out is det.

    % Like lookup, but just fails if there is no entry for the key.
    %
:- func search(hash_table(K, V), K) = V.
:- mode search(hash_table_ui, in) = out is semidet.
%:- mode search(in, in, out) is semidet.

:- pred search(hash_table(K, V), K, V).
:- mode search(hash_table_ui, in, out) is semidet.
%:- mode search(in, in, out) is semidet.

    % Convert a hash table into an association list.
    %
:- func to_assoc_list(hash_table(K, V)) = assoc_list(K, V).
:- mode to_assoc_list(hash_table_ui) = out is det.
%:- mode to_assoc_list(in) = out is det.

    % Fold a function over the key-value bindings in a hash table.
    %
:- func fold(func(K, V, T) = T, hash_table(K, V), T) = T.
:- mode fold(func(in, in, in) = out is det, hash_table_ui, in) = out is det.
:- mode fold(func(in, in, di) = uo is det, hash_table_ui, di) = uo is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:int, Next:, Previous:hash_table, Up:Top

28 int


%--------------------------------------------------%
% Copyright (C) 1994-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: int.m.
% Main authors: conway, fjh.
% Stability: medium.
%
% Predicates and functions for dealing with machine-size integer numbers.
%
% The behaviour of a computation for which overflow occurs is undefined.
% (In the current implementation, the predicates and functions in this
% module do not check for overflow, and the results you get are those
% delivered by the C compiler.  However, future implementations
% might check for overflow.)
%
%--------------------------------------------------%

:- module int.

:- interface.

:- import_module array, enum.

:- instance enum(int).

	% less than
:- pred int < int.
:- mode in  < in is semidet.

	% greater than
:- pred int > int.
:- mode in  > in is semidet.

	% less than or equal
:- pred int =< int.
:- mode in  =< in is semidet.

	% greater than or equal
:- pred int >= int.
:- mode in >= in is semidet.

	% absolute value
:- func int__abs(int) = int.
:- pred int__abs(int, int).
:- mode int__abs(in, out) is det.

	% maximum
:- func int__max(int, int) = int.
:- pred int__max(int, int, int).
:- mode int__max(in, in, out) is det.

	% minimum
:- func int__min(int, int) = int.
:- pred int__min(int, int, int).
:- mode int__min(in, in, out) is det.

	% conversion of integer to floating point
	% OBSOLETE: use float__float/1 instead.
:- pred int__to_float(int, float) is det.
:- mode int__to_float(in, out) is det.

	% expontiation
	% int__pow(X, Y, Z): Z is X raised to the Yth power
	% Throws a `math__domain_error' exception if Y is negative.
:- func int__pow(int, int) = int.
:- pred int__pow(int, int, int).
:- mode int__pow(in, in, out) is det.

	% base 2 logarithm
	% int__log2(X) = N is the least integer such that 2 to the
	% power N is greater than or equal to X.
	% Throws a `math__domain_error' exception if X is not positive.
:- func int__log2(int) = int.
:- pred int__log2(int, int).
:- mode int__log2(in, out) is det.

	% addition
:- func int + int = int.
:- mode in  + in  = uo  is det.
:- mode uo  + in  = in  is det.
:- mode in  + uo  = in  is det.

:- func int__plus(int, int) = int.

	% multiplication
:- func int * int = int.
:- mode in  * in  = uo  is det.

:- func int__times(int, int) = int.

	% subtraction
:- func int - int = int.
:- mode in  - in  = uo  is det.
:- mode uo  - in  = in  is det.
:- mode in  - uo  = in  is det.

:- func int__minus(int, int) = int.

	% flooring integer division
	% Truncates towards minus infinity, e.g. (-10) // 3 = (-4).
	%
	% Throws a `math__domain_error' exception if the right operand
	% is zero. See the comments at the top of math.m to find out how to
	% disable domain checks.
:- func div(int, int) = int.
:- mode div(in, in) = uo is det.

	% truncating integer division
	% Truncates towards zero, e.g. (-10) // 3 = (-3).
	% `div' has nicer mathematical properties for negative operands,
	% but `//' is typically more efficient.
	%
	% Throws a `math__domain_error' exception if the right operand
	% is zero. See the comments at the top of math.m to find out how to
	% disable domain checks.
:- func int // int = int.
:- mode in  // in  = uo  is det.

	% (/)/2 is a synonym for (//)/2 to bring Mercury into line with
	% the common convention for naming integer division.
	%
:- func int / int = int.
:- mode in  / in  = uo  is det.

	% unchecked_quotient(X, Y) is the same as X // Y, but the
	% behaviour is undefined if the right operand is zero.
:- func unchecked_quotient(int, int) = int.
:- mode unchecked_quotient(in, in)  = uo  is det.

	% modulus
	% X mod Y = X - (X div Y) * Y
:- func int mod int = int.
:- mode in  mod in  = uo  is det.

	% remainder
	% X rem Y = X - (X // Y) * Y
	% `mod' has nicer mathematical properties for negative X,
	% but `rem' is typically more efficient.
	%
	% Throws a `math__domain_error' exception if the right operand
	% is zero. See the comments at the top of math.m to find out how to
	% disable domain checks.
:- func int rem int = int.
:- mode in rem in = uo is det.

	% unchecked_rem(X, Y) is the same as X rem Y, but the
	% behaviour is undefined if the right operand is zero.
:- func unchecked_rem(int, int) = int.
:- mode unchecked_rem(in, in) = uo is det.

	% Left shift.
	% X << Y returns X "left shifted" by Y bits.
	% To be precise, if Y is negative, the result is
	% X div (2^(-Y)), otherwise the result is X * (2^Y).
:- func int << int = int.
:- mode in  << in  = uo  is det.

	% unchecked_left_shift(X, Y) is the same as X << Y
	% except that the behaviour is undefined if Y is negative,
	% or greater than or equal to the result of `int__bits_per_int/1'.
	% It will typically be implemented more efficiently than X << Y.
:- func unchecked_left_shift(int, int) = int.
:- mode unchecked_left_shift(in, in) = uo is det.

	% Right shift.
	% X >> Y returns X "arithmetic right shifted" by Y bits.
	% To be precise, if Y is negative, the result is
	% X * (2^(-Y)), otherwise the result is X div (2^Y).
:- func int >> int = int.
:- mode in  >> in  = uo  is det.

	% unchecked_right_shift(X, Y) is the same as X >> Y
	% except that the behaviour is undefined if Y is negative,
	% or greater than or equal to the result of `int__bits_per_int/1'.
	% It will typically be implemented more efficiently than X >> Y.
:- func unchecked_right_shift(int, int) = int.
:- mode unchecked_right_shift(in, in) = uo is det.

	% even(X) is equivalent to (X mod 2 = 0).
:- pred even(int).
:- mode even(in) is semidet.

	% odd(X) is equivalent to (not even(X)), i.e. (X mod 2 = 1).
:- pred odd(int).
:- mode odd(in) is semidet.

	% bitwise and
:- func int /\ int = int.
:- mode in  /\ in  = uo  is det.

	% bitwise or
:- func int \/ int = int.
:- mode in  \/ in  = uo  is det.

	% bitwise exclusive or (xor)
:- func int__xor(int, int) = int.
:- mode int__xor(in, in) = uo is det.
:- mode int__xor(in, uo) = in is det.
:- mode int__xor(uo, in) = in is det.

	% bitwise complement
:- func \ int = int.
:- mode \ in  = uo  is det.

	% unary plus
:- func + int = int.
:- mode + in = uo is det.

	% unary minus
:- func - int = int.
:- mode - in = uo is det.

	% is/2, for backwards compatiblity with Prolog (and with
:- pred is(T, T) is det.
:- mode is(uo, di) is det.
:- mode is(out, in) is det.

	% int__max_int is the maximum value of an int
	% on this machine.
:- func int__max_int = int.
:- pred int__max_int(int::out) is det.

	% int__min_int is the minimum value of an int
	% on this machine.
:- func int__min_int = int.
:- pred int__min_int(int::out) is det.

	% int__bits_per_int is the number of bits in an int
	% on this machine.
:- func int__bits_per_int = int.
:- pred int__bits_per_int(int::out) is det.

	% fold_up(F, Low, High, !Acc) <=> list.foldl(F, Low `..` High, !Acc)
	%
	% NOTE: fold_up/5 is undefined if High = int.max_int.
	%
:- pred int__fold_up(pred(int, T, T), int, int, T, T).
:- mode int__fold_up(pred(in, in, out) is det, in, in, in, out) is det.
:- mode int__fold_up(pred(in, di, uo) is det, in, in, di, uo) is det.
:- mode int__fold_up(pred(in, array_di, array_uo) is det, in, in,
	array_di, array_uo) is det.
:- mode int__fold_up(pred(in, in, out) is semidet, in, in, in, out)
	is semidet.
:- mode int__fold_up(pred(in, in, out) is nondet, in, in, in, out)
	is nondet.
:- mode int__fold_up(pred(in, di, uo) is cc_multi, in, in, di, uo)
	is cc_multi.
:- mode int__fold_up(pred(in, in, out) is cc_multi, in, in, in, out)
	is cc_multi.

	% fold_up(F, Low, High, Acc) <=> list.foldl(F, Low `..` High, Acc)
	%
	% NOTE: fold_up/4 is undefined if High = int.max_int.
	%
:- func int__fold_up(func(int, T) = T, int, int, T) = T.

	% fold_down(F, Low, High, !Acc) <=> list.foldr(F, Low `..` High, !Acc)
	%
	% NOTE: fold_down/5 is undefined if Low int.min_int.
	%
:- pred int__fold_down(pred(int, T, T), int, int, T, T).
:- mode int__fold_down(pred(in, in, out) is det, in, in, in, out) is det.
:- mode int__fold_down(pred(in, di, uo) is det, in, in, di, uo) is det.
:- mode int__fold_down(pred(in, array_di, array_uo) is det, in, in,
	array_di, array_uo) is det.
:- mode int__fold_down(pred(in, in, out) is semidet, in, in, in, out)
	is semidet.
:- mode int__fold_down(pred(in, in, out) is nondet, in, in, in, out)
	is nondet.
:- mode int__fold_down(pred(in, di, uo) is cc_multi, in, in, di, uo)
	is cc_multi.
:- mode int__fold_down(pred(in, in, out) is cc_multi, in, in, in, out)
	is cc_multi.

	% fold_down(F, Low, High, Acc) <=> list.foldr(F, Low `..` High, Acc)
	%
	% NOTE: fold_down/4 is undefined if Low = int.min_int.
	%
:- func int__fold_down(func(int, T) = T, int, int, T) = T.

	% fold_up2(F, Low, High, !Acc1, Acc2) <=>
	% 	list.foldl2(F, Low `..` High, !Acc1, !Acc2)
	%
	% NOTE: fold_up2/7 is undefined if High = int.max_int.
	%
:- pred int__fold_up2(pred(int, T, T, U, U), int, int, T, T, U, U).
:- mode int__fold_up2(pred(in, in, out, in, out) is det, in, in, in, out,
	in, out) is det.
:- mode int__fold_up2(pred(in, in, out, in, out) is semidet, in, in,
	in, out, in, out) is semidet.
:- mode int__fold_up2(pred(in, in, out, in, out) is nondet, in, in,
	in, out, in, out) is nondet.
:- mode int__fold_up2(pred(in, in, out, di, uo) is det, in, in, in, out,
	di, uo) is det.
:- mode int__fold_up2(pred(in, di, uo, di, uo) is det, in, in, di, uo,
	di, uo) is det.

	% fold_down2(F, Low, High, !Acc1, !Acc2) <=>
	% 	list.foldr2(F, Low `..` High, !Acc1, Acc2).
	%
	% NOTE: fold_down2/7 is undefined if Low = int.min_int.
	%
:- pred int__fold_down2(pred(int, T, T, U, U), int, int, T, T, U, U).
:- mode int__fold_down2(pred(in, in, out, in, out) is det, in, in, in, out,
	in, out) is det.
:- mode int__fold_down2(pred(in, in, out, in, out) is semidet, in, in,
	in, out, in, out) is semidet.
:- mode int__fold_down2(pred(in, in, out, in, out) is nondet, in, in,
	in, out, in, out) is nondet.
:- mode int__fold_down2(pred(in, in, out, di, uo) is det, in, in, in, out,
	di, uo) is det.
:- mode int__fold_down2(pred(in, di, uo, di, uo) is det, in, in, di, uo,
	di, uo) is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:integer, Next:, Previous:int, Up:Top

29 integer


%--------------------------------------------------%
% Copyright (C) 1997-2000, 2003-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: integer.m
% main authors:
% aet Mar 1998.
% Dan Hazel <odin@svrc.uq.edu.au> Oct 1999.
%
% Implements an arbitrary precision integer type and basic
% operations on it. (An arbitrary precision integer may have
% any number of digits, unlike an int, which is limited to the
% precision of the machine's int type, which is typically 32 bits.)
%
% NOTE: All operators behave as the equivalent operators on ints do.
% This includes the division operators: / // rem div mod.
%
%--------------------------------------------------%

:- module integer.

:- interface.

:- import_module string, float.

:- type integer.

:- pred '<'(integer::in, integer::in) is semidet.

:- pred '>'(integer::in, integer::in) is semidet.

:- pred '=<'(integer::in, integer::in) is semidet.

:- pred '>='(integer::in, integer::in) is semidet.

:- func integer__integer(int) = integer.

:- func integer__to_string(integer) = string.

:- func integer__from_string(string::in) = (integer::out) is semidet.

:- func '+'(integer) = integer.

:- func '-'(integer) = integer.

:- func integer + integer = integer.

:- func integer - integer = integer.

:- func integer * integer = integer.

:- func integer // integer = integer.

:- func integer div integer = integer.

:- func integer rem integer = integer.

:- func integer mod integer = integer.

:- func integer << int = integer.

:- func integer >> int = integer.

:- func integer /\ integer = integer.

:- func integer \/ integer = integer.

:- func integer `xor` integer = integer.

:- func \ integer = integer.

:- func integer__abs(integer) = integer.

:- pred integer__pow(integer::in, integer::in, integer::out) is det.
:- func integer__pow(integer, integer) = integer.

:- func integer__float(integer) = float.
:- func integer__int(integer) = int.

:- func integer__zero = integer.

:- func integer__one = integer.

%--------------------------------------------------%
%--------------------------------------------------%


Node:io, Next:, Previous:integer, Up:Top

30 io


%-----------------------------------------------------------------------------r
% 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: io.m.
% Main author: fjh.
% Stability: medium to high.
%
% This file encapsulates all the file I/O.
%
% We implement a purely logical I/O system using non-logical I/O primitives
% of the underlying system (C, Java or IL).
% We ensure referential transparency by passing around a ``state-of-the-world''
% argument using unique modes. The compiler will check that the state of the
% world argument is properly single-threaded, and will also ensure that you
% don't attempt to backtrack over any I/O.
%
% Attempting any operation on a stream which has already been closed results
% in undefined behaviour.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module io.
:- interface.

:- import_module bool, char, string, std_util, list, map, time, deconstruct.

%--------------------------------------------------%

% Exported types

	% The state of the universe.

:- type io__state.

	% An alternative, more concise name for `io__state'.

:- type io__io == io__state.

	% Opaque handles for text I/O streams.

:- type io__input_stream.

:- type io__output_stream.

	% Opaque handles for binary I/O streams.

:- type io__binary_input_stream		==	io__binary_stream.

:- type io__binary_output_stream	==	io__binary_stream.

:- type io__binary_stream.

	% a unique identifier for an IO stream
:- type io__stream_id.

	% Various types used for the result from the access predicates

:- type io__res
	--->	ok
	;	error(io__error).

:- type io__res(T)
	--->	ok(T)
	;	error(io__error).

	% io__maybe_partial_res is used where it is possible to return
	% a partial result when an error occurs,
:- type io__maybe_partial_res(T)
	--->	ok(T)
	;	error(T, io__error).

:- type io__result
	--->	ok
	;	eof
	;	error(io__error).

:- type io__result(T)
	--->	ok(T)
	;	eof
	;	error(io__error).

:- type io__read_result(T)
	--->	ok(T)
	;	eof
	;	error(string, int).	% error message, line number

:- type io__error.	% Use io__error_message to decode it.

	% Poly-type is used for io__write_many and io__format,
	% which do printf-like formatting.

:- type io__poly_type == string__poly_type.

	% io__whence denotes the base for a seek operation.
	% 	set	- seek relative to the start of the file
	%	cur	- seek relative to the current position in the file
	%	end	- seek relative to the end of the file.

:- type io__whence
	--->	set
	;	cur
	;	end.

%--------------------------------------------------%

% Text input predicates.

	% Reads a character from the current input stream.
:- pred io__read_char(io__result(char)::out, io::di, io::uo) is det.

	% Reads a whitespace delimited word from the current input stream.
:- pred io__read_word(io__result(list(char))::out, io::di, io::uo) is det.

	% Reads a line from the current input stream, returns the
	% the result as a list of chars.
:- pred io__read_line(io__result(list(char))::out, io::di, io::uo) is det.

	% Reads a line from the current input stream, returns the
	% result as a string.
:- pred io__read_line_as_string(io__result(string)::out, io::di, io::uo)
	is det.

	% Reads all the characters from the current input stream until
	% eof or error.
:- pred io__read_file(io__maybe_partial_res(list(char))::out, io::di, io::uo)
	is det.

	% Reads all the characters from the current input stream until
	% eof or error.  Returns the result as a string rather than
	% as a list of char.
:- pred io__read_file_as_string(io__maybe_partial_res(string)::out,
	io::di, io::uo) is det.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl(pred(char, T, T), T, io__maybe_partial_res(T),
	io, io).
:- mode io__input_stream_foldl((pred(in, in, out) is det), in, out,
	di, uo) is det.
:- mode io__input_stream_foldl((pred(in, in, out) is cc_multi), in, out,
	di, uo) is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl_io(pred(char, io, io), io__res, io, io).
:- mode io__input_stream_foldl_io((pred(in, di, uo) is det), out, di, uo)
	is det.
:- mode io__input_stream_foldl_io((pred(in, di, uo) is cc_multi), out, di, uo)
	is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl2_io(pred(char, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__input_stream_foldl2_io((pred(in, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__input_stream_foldl2_io((pred(in, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error, or the
	% closure returns `no' as its second argument.
:- pred io__input_stream_foldl2_io_maybe_stop(
	pred(char, bool, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__input_stream_foldl2_io_maybe_stop(
	(pred(in, out, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__input_stream_foldl2_io_maybe_stop(
	(pred(in, out, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Un-reads a character from the current input stream.
	% You can put back as many characters as you like.
	% You can even put back something that you didn't actually read.
	% Note: `io__putback_char' uses the C library function ungetc().
	% On some systems only one character of pushback is guaranteed.
	% `io__putback_char' will throw an io__error exception
	% if ungetc() fails.
:- pred io__putback_char(char::in, io::di, io::uo) is det.

	% Reads a character from specified stream.
:- pred io__read_char(io__input_stream::in, io__result(char)::out,
	io::di, io::uo) is det.

	% Reads a whitespace delimited word from specified stream.
:- pred io__read_word(io__input_stream::in, io__result(list(char))::out,
	io::di, io::uo) is det.

	% Reads a line from specified stream, returning the result
	% as a list of chars.
:- pred io__read_line(io__input_stream::in, io__result(list(char))::out,
	io::di, io::uo) is det.

	% Reads a line from specified stream, returning the
	% result as a string.
:- pred io__read_line_as_string(io__input_stream::in, io__result(string)::out,
	io::di, io::uo) is det.

	% Reads all the characters from the given input stream until
	% eof or error.
:- pred io__read_file(io__input_stream::in,
	io__maybe_partial_res(list(char))::out, io::di, io::uo) is det.

	% Reads all the characters from the given input stream until
	% eof or error.  Returns the result as a string rather than
	% as a list of char.
:- pred io__read_file_as_string(io__input_stream::in,
	io__maybe_partial_res(string)::out, io::di, io::uo) is det.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl(io__input_stream, pred(char, T, T),
	T, io__maybe_partial_res(T), io, io).
:- mode io__input_stream_foldl(in, in(pred(in, in, out) is det),
	in, out, di, uo) is det.
:- mode io__input_stream_foldl(in, in(pred(in, in, out) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl_io(io__input_stream, pred(char, io, io),
	io__res, io, io).
:- mode io__input_stream_foldl_io(in, in(pred(in, di, uo) is det),
	out, di, uo) is det.
:- mode io__input_stream_foldl_io(in, in(pred(in, di, uo) is cc_multi),
	out, di, uo) is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error.
:- pred io__input_stream_foldl2_io(io__input_stream,
	pred(char, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__input_stream_foldl2_io(in,
	in(pred(in, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__input_stream_foldl2_io(in,
	in(pred(in, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each character read from
	% the input stream in turn, until eof or error, or the
	% closure returns `no' as its second argument.
:- pred io__input_stream_foldl2_io_maybe_stop(io__input_stream,
	pred(char, bool, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__input_stream_foldl2_io_maybe_stop(in,
	(pred(in, out, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__input_stream_foldl2_io_maybe_stop(in,
	(pred(in, out, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Un-reads a character from specified stream.
	% You can put back as many characters as you like.
	% You can even put back something that you didn't actually read.
	% Note: `io__putback_char' uses the C library function ungetc().
	% On some systems only one character of pushback is guaranteed.
	% `io__putback_char' will throw an io__error exception
	% if ungetc() fails.
:- pred io__putback_char(io__input_stream::in, char::in, io::di, io::uo)
	is det.

	% Reads a ground term of any type, written using standard
	% Mercury syntax, from the current or specified input stream.
	% The type of the term read is determined by the context
	% in which `io__read' is used.
	%
	% First, the input stream is read until an end-of-term token,
	% end-of-file, or I/O error is reached.  (An end-of-term
	% token consists of a `.' followed by whitespace.
	% The trailing whitespace is left in the input stream.)
	%
	% Then, the result is determined according to the tokens read.
	% If there were no non-whitespace characters before the
	% end of file, then `io__read' returns `eof'.
	% If the tokens read formed a syntactically correct ground term
	% of the correct type, followed by an end-of-term token,
	% then it returns `ok(Term)'.  If characters read from
	% the input stream did not form a syntactically
	% correct term, or if the term read is not a ground term,
	% or if the term is not a valid term of the appropriate type,
	% or if an I/O error is encountered, then it returns
	% `error(Message, LineNumber)'.
:- pred io__read(io__read_result(T)::out, io::di, io::uo) is det.
:- pred io__read(io__input_stream::in, io__read_result(T)::out, io::di, io::uo)
	is det.

	% The type `posn' represents a position within a string.
:- type posn
	--->	posn(int, int, int).
		% line number, offset of start of line, current offset
		% (the first two are used only for the purposes of
		% computing term_contexts, for use e.g. in error messages).
		% Offsets start at zero.

	% io__read_from_string(FileName, String, MaxPos, Result, Posn0, Posn):
	% Same as io__read/4 except that it reads from
	% a string rather than from a stream.
	% FileName is the name of the source (for use in error messages).
	% String is the string to be parsed.
	% Posn0 is the position to start parsing from.
	% Posn is the position one past where the term read in ends.
	% MaxPos is the offset in the string which should be
	% considered the end-of-stream -- this is the upper bound
	% for Posn.  (In the usual case, MaxPos is just the length
	% of the String.)
	% WARNING: if MaxPos > length of String then the behaviour
	% is UNDEFINED.
:- pred io__read_from_string(string::in, string::in, int::in,
	io__read_result(T)::out, posn::in, posn::out) is det.

	% Discards all the whitespace from the current stream.
:- pred io__ignore_whitespace(io__result::out, io::di, io::uo) is det.

	% Discards all the whitespace from the specified stream.
:- pred io__ignore_whitespace(io__input_stream::in, io__result::out,
	io::di, io::uo) is det.

%--------------------------------------------------%

% Text output predicates.
% These will all throw an io__error exception if an I/O error occurs.

	% io__print/3 writes its argument to the standard output stream.
	% io__print/4 writes its second argument to the output stream
	% specified in its first argument.
	% In all cases, the argument to output can be of any type.
	% It is output in a format that is intended to be human readable.
	%
	% If the argument is just a single string or character, it
	% will be printed out exactly as is (unquoted).
	% If the argument is of type univ, then it will print out
	% the value stored in the univ, but not the type.
	%
	% io__print/5 is the same as io__print/4 except that it allows
	% the caller to specify how non-canonical types should be handled.
	% io__print/3 and io__print/4 implicitly specify `canonicalize'
	% as the method for handling non-canonical types.  This means
	% that for higher-order types, or types with user-defined
	% equality axioms, or types defined using the foreign language
	% interface (i.e. c_pointer type or pragma foreign_type),
	% the text output will only describe the type that is being
	% printed, not the value.
	%
	% io__print_cc/3 is the same as io__print/3 except that it
	% specifies `include_details_cc' rather than `canonicalize'.
	% This means that it will print the details of non-canonical
	% types.  However, it has determinism `cc_multi'.
	%
	% Note that even if `include_details_cc' is specified,
	% some implementations may not be able to print all the details
	% for higher-order types or types defined using the foreign
	% language interface.

:- pred io__print(T::in, io::di, io::uo) is det.

:- pred io__print(io__output_stream::in, T::in, io::di, io::uo) is det.

:- pred io__print(io__output_stream, deconstruct__noncanon_handling, T,
	io, io).
:- mode io__print(in, in(do_not_allow), in, di, uo) is det.
:- mode io__print(in, in(canonicalize), in, di, uo) is det.
:- mode io__print(in, in(include_details_cc), in, di, uo) is cc_multi.
:- mode io__print(in, in, in, di, uo) is cc_multi.

:- pred io__print_cc(T::in, io::di, io::uo) is cc_multi.

	% io__write/3 writes its argument to the current output stream.
	% io__write/4 writes its second argument to the output stream
	% specified in its first argument.
	% In all cases, the argument to output may be of any type.
	% The argument is written in a format that is intended to
	% be valid Mercury syntax whenever possible.
	%
	% Strings and characters are always printed out in quotes,
	% using backslash escapes if necessary.
	% For higher-order types, or for types defined using the
	% foreign language interface (pragma foreign_code), the text
	% output will only describe the type that is being printed, not
	% the value, and the result may not be parsable by `io__read'.
	% For the types containing existential quantifiers,
	% the type `type_desc' and closure types, the result may not be
	% parsable by `io__read', either.  But in all other cases the
	% format used is standard Mercury syntax, and if you append a
	% period and newline (".\n"), then the results can be read in
	% again using `io__read'.
	%
	% io__write/5 is the same as io__write/4 except that it allows
	% the caller to specify how non-canonical types should be handled.
	% io__write_cc/3 is the same as io__write/3 except that it
	% specifies `include_details_cc' rather than `canonicalize'.

:- pred io__write(T::in, io::di, io::uo) is det.

:- pred io__write(io__output_stream::in, T::in, io::di, io::uo) is det.

:- pred io__write(io__output_stream, deconstruct__noncanon_handling, T,
	io, io).
:- mode io__write(in, in(do_not_allow), in, di, uo) is det.
:- mode io__write(in, in(canonicalize), in, di, uo) is det.
:- mode io__write(in, in(include_details_cc), in, di, uo) is cc_multi.
:- mode io__write(in, in, in, di, uo) is cc_multi.

:- pred io__write_cc(T::in, io::di, io::uo) is cc_multi.

	% Writes a newline character to the current output stream.
:- pred io__nl(io::di, io::uo) is det.

	% Writes a newline character to the specified output stream.
:- pred io__nl(io__output_stream::in, io::di, io::uo) is det.

	% Writes a string to the current output stream.
:- pred io__write_string(string::in, io::di, io::uo) is det.

	% Writes a string to the specified output stream.
:- pred io__write_string(io__output_stream::in, string::in, io::di, io::uo)
	is det.

	% Writes a list of strings to the current output stream.
:- pred io__write_strings(list(string)::in, io::di, io::uo) is det.

	% Writes a list of strings to the specified output stream.
:- pred io__write_strings(io__output_stream::in, list(string)::in,
	io::di, io::uo) is det.

	% Writes a character to the current output stream.
:- pred io__write_char(char::in, io::di, io::uo) is det.

	% Writes a character to the specified output stream.
:- pred io__write_char(io__output_stream::in, char::in, io::di, io::uo) is det.

	% Writes an integer to the current output stream.
:- pred io__write_int(int::in, io::di, io::uo) is det.

	% Writes an integer to the specified output stream.
:- pred io__write_int(io__output_stream::in, int::in, io::di, io::uo) is det.

	% Writes a floating point number to the current output stream.
:- pred io__write_float(float::in, io::di, io::uo) is det.

	% Writes a floating point number to the specified output stream.
:- pred io__write_float(io__output_stream::in, float::in, io::di, io::uo)
	is det.

	% Formats the specified arguments according to the format string,
	% using string__format, and then writes the result to the current
	% output stream. (See the documentation of string__format for details.)
:- pred io__format(string::in, list(io__poly_type)::in, io::di, io::uo) is det.

	% Formats the specified argument list according to the format string,
	% using string__format, and then writes the result to the specified
	% output stream. (See the documentation of string__format for details.)
:- pred io__format(io__output_stream::in, string::in, list(io__poly_type)::in,
	io::di, io::uo) is det.

	% Writes the specified arguments to the current output stream.
:- pred io__write_many(list(io__poly_type)::in, io::di, io::uo) is det.

	% Writes the specified arguments to the specified output stream.
:- pred io__write_many(io__output_stream::in, list(io__poly_type)::in,
	io::di, io::uo) is det.

	% io__write_list(List, Separator, OutputPred, !IO):
	% applies OutputPred to each element of List, printing Separator
	% between each element. Outputs to the current output stream.
:- pred io__write_list(list(T), string, pred(T, io, io), io, io).
:- mode io__write_list(in, in, pred(in, di, uo) is det, di, uo) is det.
:- mode io__write_list(in, in, pred(in, di, uo) is cc_multi, di, uo)
	is cc_multi.

	% io__write_list(Stream, List, Separator, OutputPred, !IO):
	% applies OutputPred to each element of List, printing Separator
	% between each element. Outputs to Stream.
:- pred io__write_list(io__output_stream, list(T), string,
	pred(T, io, io), io, io).
:- mode io__write_list(in, in, in, pred(in, di, uo) is det, di, uo) is det.
:- mode io__write_list(in, in, in, pred(in, di, uo) is cc_multi, di, uo)
	is cc_multi.

	% Flush the output buffer of the current output stream.
:- pred io__flush_output(io::di, io::uo) is det.

	% Flush the output buffer of the specified output stream.
:- pred io__flush_output(io__output_stream::in, io::di, io::uo) is det.

%--------------------------------------------------%

% Input text stream predicates.

	% io__see(File, Result, !IO):
	% Attempts to open a file for input, and if successful,
	% sets the current input stream to the newly opened stream.
	% Result is either 'ok' or 'error'.
:- pred io__see(string::in, io__res::out, io::di, io::uo) is det.

	% Closes the current input stream.
	% The current input stream reverts to standard input.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__seen(io::di, io::uo) is det.

	% Attempts to open a file for input.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_input(string::in, io__res(io__input_stream)::out,
	io::di, io::uo) is det.

	% Closes an open input stream.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__close_input(io__input_stream::in, io::di, io::uo) is det.

	% Retrieves the current input stream.
	% Does not modify the IO state.
:- pred io__input_stream(io__input_stream::out, io::di, io::uo) is det.

	% io__set_input_stream(NewStream, OldStream, !IO):
	% Changes the current input stream to the stream specified.
	% Returns the previous stream.
:- pred io__set_input_stream(io__input_stream::in, io__input_stream::out,
	io::di, io::uo) is det.

	% Retrieves the standard input stream.
	% Does not modify the IO state.
:- pred io__stdin_stream(io__input_stream::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the current input
	% stream.
	% For file streams, this is the filename.
	% For stdin this is the string "<standard input>".
:- pred io__input_stream_name(string::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the specified input
	% stream.
	% For file streams, this is the filename.
	% For stdin this is the string "<standard input>".
:- pred io__input_stream_name(io__input_stream::in, string::out,
	io::di, io::uo) is det.

	% Return the line number of the current input stream.
	% Lines are normally numbered starting at 1
	% (but this can be overridden by calling io__set_line_number).
:- pred io__get_line_number(int::out, io::di, io::uo) is det.

	% Return the line number of the specified input stream.
	% Lines are normally numbered starting at 1
	% (but this can be overridden by calling io__set_line_number).
:- pred io__get_line_number(io__input_stream::in, int::out, io::di, io::uo)
	is det.

	% Set the line number of the current input stream.
:- pred io__set_line_number(int::in, io::di, io::uo) is det.

	% Set the line number of the specified input stream.
:- pred io__set_line_number(io__input_stream::in, int::in, io::di, io::uo)
	is det.

%--------------------------------------------------%

% Output text stream predicates.

	% Attempts to open a file for output, and if successful
	% sets the current output stream to the newly opened stream.
	% As per Prolog tell/1. Result is either 'ok' or 'error(ErrCode)'.
:- pred io__tell(string::in, io__res::out, io::di, io::uo) is det.

	% Closes the current output stream; the default output stream
	% reverts to standard output. As per Prolog told/0.
	% This will throw an io__error exception if an I/O error occurs.
:- pred io__told(io::di, io::uo) is det.

	% Attempts to open a file for output.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_output(string::in, io__res(io__output_stream)::out,
	io::di, io::uo) is det.

	% Attempts to open a file for appending.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_append(string::in, io__res(io__output_stream)::out,
	io::di, io::uo) is det.

	% Closes an open output stream.
	% This will throw an io__error exception if an I/O error occurs.
:- pred io__close_output(io__output_stream::in, io::di, io::uo) is det.

	% Retrieves the current output stream.
	% Does not modify the IO state.
:- pred io__output_stream(io__output_stream::out, io::di, io::uo) is det.

	% io__set_output_stream(NewStream, OldStream, !IO):
	% Changes the current output stream to the stream specified.
	% Returns the previous stream.
:- pred io__set_output_stream(io__output_stream::in, io__output_stream::out,
	io::di, io::uo) is det.

	% Retrieves the standard output stream.
	% Does not modify the IO state.
:- pred io__stdout_stream(io__output_stream::out, io::di, io::uo) is det.

	% Retrieves the standard error stream.
	% Does not modify the IO state.
:- pred io__stderr_stream(io__output_stream::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the current
	% output stream.
	% For file streams, this is the filename.
	% For stdout this is the string "<standard output>".
	% For stderr this is the string "<standard error>".
:- pred io__output_stream_name(string::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the specified
	% stream.
	% For file streams, this is the filename.
	% For stdout this is the string "<standard output>".
	% For stderr this is the string "<standard error>".
:- pred io__output_stream_name(io__output_stream::in, string::out,
	io::di, io::uo) is det.

	% Return the line number of the current output stream.
	% Lines are normally numbered starting at 1
	% (but this can be overridden by calling io__set_output_line_number).
:- pred io__get_output_line_number(int::out, io::di, io::uo) is det.

	% Return the line number of the specified output stream.
	% Lines are normally numbered starting at 1
	% (but this can be overridden by calling io__set_output_line_number).
:- pred io__get_output_line_number(io__output_stream::in, int::out,
	io::di, io::uo) is det.

	% Set the line number of the current output stream.
:- pred io__set_output_line_number(int::in, io::di, io::uo) is det.

	% Set the line number of the specified output stream.
:- pred io__set_output_line_number(io__output_stream::in, int::in,
	io::di, io::uo) is det.

%--------------------------------------------------%

% Binary input predicates.

	% Reads a binary representation of a term of type T
	% from the current binary input stream.
:- pred io__read_binary(io__result(T)::out, io::di, io::uo) is det.

	% Reads a binary representation of a term of type T
	% from the specified binary input stream.
	%
	% Note: if you attempt to read a binary representation written
	% by a different program, or a different version of the same
	% program, then the results are not guaranteed to be meaningful.
	% Another caveat is that higher-order types cannot be read.
	% (If you try, you will get a runtime error.)
	%
	% XXX Note also that due to the current implementation,
	% io__read_binary will not work for the Java back-end.
:- pred io__read_binary(io__binary_input_stream::in, io__result(T)::out,
	io::di, io::uo) is det.

	% Reads a single 8-bit byte from the current binary input stream.
:- pred io__read_byte(io__result(int)::out, io::di, io::uo) is det.

	% Reads a single 8-bit byte from the specified binary input stream.
:- pred io__read_byte(io__binary_input_stream::in, io__result(int)::out,
	io::di, io::uo) is det.

	% Reads all the bytes from the current binary input stream
	% until eof or error.
:- pred io__read_binary_file(io__result(list(int))::out, io::di, io::uo)
	is det.

	% Reads all the bytes from the given binary input stream until
	% eof or error.
:- pred io__read_binary_file(io__input_stream::in, io__result(list(int))::out,
	io::di, io::uo) is det.

	% Applies the given closure to each byte read from the
	% current binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl(pred(int, T, T),
	T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl((pred(in, in, out) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl((pred(in, in, out) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% current binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl_io(pred(int, io, io),
	io__res, io, io).
:- mode io__binary_input_stream_foldl_io((pred(in, di, uo) is det),
	out, di, uo) is det.
:- mode io__binary_input_stream_foldl_io((pred(in, di, uo) is cc_multi),
	out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% current binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl2_io(
	pred(int, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl2_io(
	in(pred(in, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl2_io(
	in(pred(in, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% current binary input stream in turn, until eof or error,
	% or the closure returns `no' as its second argument.
:- pred io__binary_input_stream_foldl2_io_maybe_stop(
	pred(int, bool, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl2_io_maybe_stop(
	(pred(in, out, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl2_io_maybe_stop(
	(pred(in, out, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% given binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl(io__binary_input_stream,
	pred(int, T, T), T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl(in, in(pred(in, in, out) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl(in, in(pred(in, in, out) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% given binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl_io(io__binary_input_stream,
	pred(int, io, io), io__res, io, io).
:- mode io__binary_input_stream_foldl_io(in, in(pred(in, di, uo) is det),
	out, di, uo) is det.
:- mode io__binary_input_stream_foldl_io(in, in(pred(in, di, uo) is cc_multi),
	out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% given binary input stream in turn, until eof or error.
:- pred io__binary_input_stream_foldl2_io(io__binary_input_stream,
	pred(int, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl2_io(in,
	(pred(in, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl2_io(in,
	(pred(in, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Applies the given closure to each byte read from the
	% given binary input stream in turn, until eof or error,
	% or the closure returns `no' as its second argument.
:- pred io__binary_input_stream_foldl2_io_maybe_stop(
	io__binary_input_stream,
	pred(int, bool, T, T, io, io),
	T, io__maybe_partial_res(T), io, io).
:- mode io__binary_input_stream_foldl2_io_maybe_stop(in,
	(pred(in, out, in, out, di, uo) is det),
	in, out, di, uo) is det.
:- mode io__binary_input_stream_foldl2_io_maybe_stop(in,
	(pred(in, out, in, out, di, uo) is cc_multi),
	in, out, di, uo) is cc_multi.

	% Un-reads a byte from the current binary input stream.
	% You can put back as many bytes as you like.
	% You can even put back something that you didn't actually read.
	% The byte is taken from the bottom 8 bits of an integer.
	% Note: `io__putback_byte' uses the C library function ungetc().
	% On some systems only one byte of pushback is guaranteed.
	% `io__putback_byte' will throw an io__error exception
	% if ungetc() fails.
:- pred io__putback_byte(int::in, io::di, io::uo) is det.

	% Un-reads a byte from specified binary input stream.
	% You can put back as many bytes as you like.
	% You can even put back something that you didn't actually read.
	% The byte is returned in the bottom 8 bits of an integer.
	% Note: `io__putback_byte' uses the C library function ungetc().
	% On some systems only one byte of pushback is guaranteed.
	% `io__putback_byte' will throw an io__error exception
	% if ungetc() fails.
:- pred io__putback_byte(io__binary_input_stream::in, int::in,
	io::di, io::uo) is det.

%--------------------------------------------------%

	% Binary output predicates.
	% These will all throw an io__error exception if an I/O error occurs.
	% XXX what about wide characters?

	% Writes a binary representation of a term to the current
	% binary output stream, in a format suitable for reading
	% in again with io__read_binary.
:- pred io__write_binary(T::in, io::di, io::uo) is det.

	% Writes a binary representation of a term to the specified
	% binary output stream, in a format suitable for reading
	% in again with io__read_binary.
	%
	% XXX Note that due to the current implementation,
	% io__write_binary will not work for the Java back-end.
:- pred io__write_binary(io__binary_output_stream::in, T::in, io::di, io::uo)
	is det.

	% Writes a single byte to the current binary output stream.
	% The byte is taken from the bottom 8 bits of an int.
:- pred io__write_byte(int::in, io::di, io::uo) is det.

	% Writes a single byte to the specified binary output stream.
	% The byte is taken from the bottom 8 bits of an int.
:- pred io__write_byte(io__binary_output_stream::in, int::in, io::di, io::uo)
	is det.

	% Writes several bytes to the current binary output stream.
	% The bytes are taken from a string.
:- pred io__write_bytes(string::in, io::di, io::uo) is det.

	% Writes several bytes to the specified binary output stream.
	% The bytes are taken from a string.
:- pred io__write_bytes(io__binary_output_stream::in, string::in,
	io::di, io::uo) is det.

	% Flush the output buffer of the current binary output stream.
:- pred io__flush_binary_output(io::di, io::uo) is det.

	% Flush the output buffer of the specified binary output stream.
:- pred io__flush_binary_output(io__binary_output_stream::in,
	io::di, io::uo) is det.

	% Seek to an offset relative to Whence (documented above)
	% on a specified binary stream. Attempting to seek on a pipe
	% or tty results in implementation dependent behaviour.
:- pred io__seek_binary(io__binary_stream::in, io__whence::in, int::in,
	io::di, io::uo) is det.

	% Returns the offset (in bytes) into the specified binary stream.
:- pred io__binary_stream_offset(io__binary_stream::in, int::out,
	io::di, io::uo) is det.

%--------------------------------------------------%

	% Binary input stream predicates.

	% Attempts to open a file for binary input, and if successful
	% sets the current binary input stream to the newly opened stream.
	% Result is either 'ok' or 'error'.
:- pred io__see_binary(string::in, io__res::out, io::di, io::uo) is det.

	% Closes the current input stream.
	% The current input stream reverts to standard input.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__seen_binary(io::di, io::uo) is det.

	% Attempts to open a binary file for input.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_binary_input(string::in,
	io__res(io__binary_input_stream)::out, io::di, io::uo) is det.

	% Closes an open binary input stream.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__close_binary_input(io__binary_input_stream::in,
	io::di, io::uo) is det.

	% Retrieves the current binary input stream.
	% Does not modify the IO state.
:- pred io__binary_input_stream(io__binary_input_stream::out,
	io::di, io::uo) is det.

	% io__set_binary_input_stream(NewStream, OldStream, !IO):
	% Changes the current input stream to the stream specified.
	% Returns the previous stream.
:- pred io__set_binary_input_stream(io__binary_input_stream::in,
	io__binary_input_stream::out, io::di, io::uo) is det.

	% Retrieves the standard binary input stream.
	% Does not modify the IO state.
:- pred io__stdin_binary_stream(io__binary_input_stream::out,
	io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the current binary
	% input stream. For file streams, this is the filename.
:- pred io__binary_input_stream_name(string::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the specified
	% binary input stream. For file streams, this is the filename.
:- pred io__binary_input_stream_name(io__binary_input_stream::in, string::out,
	io::di, io::uo) is det.

%--------------------------------------------------%

	% Binary output stream predicates.

	% Attempts to open a file for binary output, and if successful
	% sets the current binary output stream to the newly opened
	% stream. As per Prolog tell/1. Result is either 'ok' or
	% 'error(ErrCode)'.
:- pred io__tell_binary(string::in, io__res::out, io::di, io::uo) is det.

	% Closes the current binary output stream.
	% The default binary output stream reverts to standard output.
	% As per Prolog told/0.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__told_binary(io::di, io::uo) is det.

	% Attempts to open a file for binary output.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_binary_output(string::in,
	io__res(io__binary_output_stream)::out, io::di, io::uo) is det.

	% Attempts to open a file for binary appending.
	% Result is either 'ok(Stream)' or 'error(ErrorCode)'.
:- pred io__open_binary_append(string::in,
	io__res(io__binary_output_stream)::out, io::di, io::uo) is det.

	% Closes an open binary output stream.
	% This will throw an io__error exception
	% if an I/O error occurs.
:- pred io__close_binary_output(io__binary_output_stream::in,
	io::di, io::uo) is det.

	% Retrieves the current binary output stream.
	% Does not modify the IO state.
:- pred io__binary_output_stream(io__binary_output_stream::out,
	io::di, io::uo) is det.

	% Retrieves the standard binary output stream.
	% Does not modify the IO state.
:- pred io__stdout_binary_stream(io__binary_output_stream::out,
	io::di, io::uo) is det.

	% io__set_binary_output_stream(NewStream, OldStream, !IO):
	% Changes the current binary output stream to the stream
	% specified. Returns the previous stream.
:- pred io__set_binary_output_stream(io__binary_output_stream::in,
	io__binary_output_stream::out, io::di, io::uo) is det.

%	Retrieves the human-readable name associated with the current
%	binary output stream.
%	For file streams, this is the filename.
:- pred io__binary_output_stream_name(string::out, io::di, io::uo) is det.

	% Retrieves the human-readable name associated with the specified
	% output stream. For file streams, this is the filename.
:- pred io__binary_output_stream_name(io__binary_output_stream::in,
	string::out, io::di, io::uo) is det.

%--------------------------------------------------%

	% Global state predicates.

	% io__progname(DefaultProgname, Progname):
	% Returns the name that the program was invoked with, if available,
	% or DefaultProgname if the name is not available.
	% Does not modify the IO state.
:- pred io__progname(string::in, string::out, io::di, io::uo) is det.

	% io__progname_base(DefaultProgname, Progname):
	% Like `io__progname', except that it strips off any path name
	% preceding the program name.  Useful for error messages.
:- pred io__progname_base(string::in, string::out, io::di, io::uo) is det.

	% Returns the arguments that the program was invoked with,
	% if available, otherwise an empty list.
	% Does not modify the IO state.
:- pred io__command_line_arguments(list(string)::out, io::di, io::uo) is det.

	% The io__state contains an integer used to record the program's exit
	% status.  When the program finishes, it will return this exit status
	% to the operating system.  The following predicates can be used
	% to get and set the exit status.

:- pred io__get_exit_status(int::out, io::di, io::uo) is det.

:- pred io__set_exit_status(int::in, io::di, io::uo) is det.

	% The io__state includes a `globals' field which is not used by the I/O
	% library, but can be used by the application. The globals field is
	% of type `univ' so that the application can store any data it wants
	% there. The following predicates can be used to access this global
	% state.

	% Doesn't modify the io__state.
:- pred io__get_globals(univ::uo, io::di, io::uo) is det.

:- pred io__set_globals(univ::di, io::di, io::uo) is det.

	% The following predicates provide an interface to the environment
	% list. Do not attempt to put spaces or '=' signs in the names of
	% environment variables, or bad things may result!

	% First argument is the name of the environment variable.
	% Returns yes(Value) if the variable was set (Value will
	% be set to the value of the variable) and no if the
	% variable was not set.
:- pred io__get_environment_var(string::in, maybe(string)::out,
	io::di, io::uo) is det.

	% First argument is the name of the environment variable,
	% second argument is the value to be assigned to that
	% variable.  Will throw an exception if the system runs
	% out of environment space.
:- pred io__set_environment_var(string::in, string::in, io::di, io::uo) is det.

%--------------------------------------------------%

% File handling predicates

	% io__make_temp(Name, !IO) creates an empty file whose name
	% is different to the name of any existing file. Name is bound
	% to the name of the file. It is the responsibility of the program
	% to delete the file when it is no longer needed.
	%
	% The file will reside in an implementation-dependent directory.
	% For current Mercury implementations, it is determined as follows:
	% 1. For the non-Java back-ends:
	%    - On Microsoft Windows systems, the file will reside in
	%      the current directory if the TMP environment variable
	%      is not set, or in the directory specified by TMP if it is set.
	%    - On Unix systems, the file will reside in /tmp if the TMPDIR
	%      environment variable is not set, or in the directory specified
	%      by TMPDIR if it is set.
	% 2. For the Java back-end, the system-dependent default
	%    temporary-file directory will be used, specified by the Java
	%    system property java.io.tmpdir. On UNIX systems the default
	%    value of this property is typically "/tmp" or "/var/tmp";
	%    on Microsoft Windows systems it is typically "c:\\temp".
:- pred io__make_temp(string::out, io::di, io::uo) is det.

	% io__mktemp(Dir, Prefix, Name, IO0, IO) creates an empty
	% file whose name is different to the name of any existing file.
	% The file will reside in the directory specified by `Dir' and will
	% have a prefix using up to the first 5 characters of `Prefix'.
	% Name is bound to the name of the file.
	% It is the responsibility of the program to delete the file
	% when it is no longer needed.
:- pred io__make_temp(string::in, string::in, string::out,
	io::di, io::uo) is det.

	% io__remove_file(FileName, Result, !IO) attempts to remove the
	% file `FileName', binding Result to ok/0 if it succeeds, or
	% error/1 if it fails.
	% If `FileName' names a file that is currently open,
	% the behaviour is implementation-dependent.
:- pred io__remove_file(string::in, io__res::out, io::di, io::uo) is det.

	% io__rename_file(OldFileName, NewFileName, Result, !IO)
	% attempts to rename the file `OldFileName' as `NewFileName',
	% binding Result to ok/0 if it succeeds, or error/1 if it fails.
	% If `OldFileName' names a file that is currently open,
	% the behaviour is implementation-dependent.
	% If `NewFileName' names a file that already exists
	% the behaviour is also implementation-dependent;
	% on some systems, the file previously named `NewFileName' will be
	% deleted and replaced with the file previously named `OldFileName'.
:- pred io__rename_file(string::in, string::in, io__res::out,
	io::di, io::uo) is det.

	% Can this platform read and create symbolic links.
:- pred io__have_symlinks is semidet.

	% io__make_symlink(FileName, LinkFileName, Result, !IO)
	% attempts to make `LinkFileName' be a symbolic link to `FileName'.
	% If `FileName' is a relative path, it is interpreted relative
	% to the directory containing `LinkFileName'.
:- pred io__make_symlink(string::in, string::in, io__res::out,
	io::di, io::uo) is det.

	% io__read_symlink(FileName, Result, !IO) returns
	% `ok(LinkTarget)' if `FileName' is a symbolic link pointing
	% to `LinkTarget', and `error(Error)' otherwise.
	% If `LinkTarget' is a relative path, it should be interpreted
	% relative the directory containing `FileName', not the current
	% directory.
:- pred io__read_symlink(string::in, io__res(string)::out, io::di, io::uo)
	is det.

:- type io__access_type
	--->	read
	;	write
	;	execute.

	% io__check_file_accessibility(FileName, AccessTypes, Result)
	% Check whether the current process can perform the operations
	% given in `AccessTypes' on `FileName'.
	% XXX When using the .NET CLI, this predicate will sometimes
	% report that a directory is writable when in fact it is not.
:- pred io__check_file_accessibility(string::in, list(access_type)::in,
	io__res::out, io::di, io::uo) is det.

:- type io__file_type
	--->	regular_file
	;	directory
	;	symbolic_link
	;	named_pipe
	;	socket
	;	character_device
	;	block_device
	;	message_queue
	;	semaphore
	;	shared_memory
	;	unknown.

	% io__file_type(FollowSymLinks, FileName, TypeResult)
	% finds the type of the given file.
:- pred io__file_type(bool::in, string::in, io__res(file_type)::out,
	io::di, io::uo) is det.

	% io__file_modification_time(FileName, TimeResult)
	% finds the last modification time of the given file.
:- pred io__file_modification_time(string::in, io__res(time_t)::out,
	io::di, io::uo) is det.

%--------------------------------------------------%

	% Memory management predicates.

	% Write memory/time usage statistics to stderr.
:- pred io__report_stats(io::di, io::uo) is det.

	% Write statistics to stderr; what statistics will be written
	% is controlled by the first argument, which acts a selector.
	% What selector values cause what statistics to be printed
	% is implementation defined.
	%
	% The Melbourne implementation supports the following selectors:
	%
	% "standard"		Writes memory/time usage statistics.
	%
	% "full_memory_stats"	Writes complete memory usage statistics,
	%			including information about all procedures
	%			and types. Requires compilation with
	%			memory profiling enabled.
	%
	% "tabling"		Writes statistics about the internals
	%			of the tabling system. Requires the runtime
	%			to have been compiled with the macro
	%			MR_TABLE_STATISTICS defined.
:- pred io__report_stats(string::in, io::di, io::uo) is det.

%--------------------------------------------------%

	% Miscellaneous predicates

	% Invokes the operating system shell with the specified
	% Command.  Result is either `ok(ExitStatus)', if it was
	% possible to invoke the command, or `error(ErrorCode)' if not.
	% The ExitStatus will be 0 if the command completed
	% successfully or the return value of the system call.  If a
	% signal kills the system call, then Result will be an error
	% indicating which signal occurred.
:- pred io__call_system(string::in, io__res(int)::out, io::di, io::uo) is det.

:- type io__system_result
	--->	exited(int)
	;	signalled(int).

	% Invokes the operating system shell with the specified
	% Command.  Result is either `ok(ExitStatus)' if it was
	% possible to invoke the command and the it ran to completion,
	% `signal(SignalNum)' if the command was killed by a signal, or
	% `error(ErrorCode)' if the command could not be executed.
	% The `ExitStatus' will be 0 if the command completed
	% successfully or the return value of the command otherwise.
:- pred io__call_system_return_signal(string::in,
	io__res(io__system_result)::out, io::di, io::uo) is det.

	% Construct an error code including the specified error message.
:- func io__make_io_error(string) = io__error.

	% Look up the error message corresponding to a particular error code.
:- func io__error_message(io__error) = string.
:- pred io__error_message(io__error::in, string::out) is det.

%--------------------------------------------------%

	% Deprecated predicates.
	%
	% Do not use these in new programs!
	% They may be deleted in the next release.

	% use io__input_stream/3 instead -- it has identical semantics
:- pragma obsolete(io__current_input_stream/3).
:- pred io__current_input_stream(io__input_stream::out, io::di, io::uo) is det.

	% use io__output_stream/3 instead -- it has identical semantics
:- pragma obsolete(io__current_output_stream/3).
:- pred io__current_output_stream(io__output_stream::out, io::di, io::uo)
	is det.

	% use io__binary_input_stream/3 instead -- it has identical semantics
:- pragma obsolete(io__current_binary_input_stream/3).
:- pred io__current_binary_input_stream(io__binary_input_stream::out,
	io::di, io::uo) is det.

	% use io__binary_output_stream/3 instead -- it has identical semantics
:- pragma obsolete(io__current_binary_output_stream/3).
:- pred io__current_binary_output_stream(io__binary_output_stream::out,
	io::di, io::uo) is det.

	% io__tmpnam(Name, !IO) binds `Name' to a temporary file name
	% which is different to the name of any existing file.
	% It will reside in /tmp if the TMPDIR environment variable
	% is not set, or in the directory specified by TMPDIR if it is set.
	% Use of this predicate is deprecated, because it may
	% result in race conditions.  Use io__make_temp/3 instead.
:- pragma obsolete(io__tmpnam/3). % use io__make_temp/3 instead
:- pred io__tmpnam(string::out, io::di, io::uo) is det.

	% io__tmpnam(Dir, Prefix, Name, !IO) binds `Name' to a
	% temporary file name which is different to the name of any
	% existing file. It will reside in the directory specified by
	% `Dir' and have a prefix using up to the first 5 characters
	% of `Prefix'.
	% Use of this predicate is deprecated, because it may
	% result in race conditions.  Use io__make_temp/5 instead.
:- pragma obsolete(io__tmpnam/5). % use io__make_temp/5 instead
:- pred io__tmpnam(string::in, string::in, string::out, io::di, io::uo) is det.

	% Write complete memory usage statistics to stderr,
	% including information about all procedures and types.
	% (You need to compile with memory profiling enabled.)
	%
	% OBSOLETE: call io__report_stats/3 instead, with the first argument
	% specified as "full_memory_stats".
:- pragma obsolete(io__report_full_memory_stats/2).
:- pred io__report_full_memory_stats(io::di, io::uo) is det.

%--------------------------------------------------%
%--------------------------------------------------%


Node:lexer, Next:, Previous:io, Up:Top

31 lexer


%--------------------------------------------------%
% Copyright (C) 1993-2000, 2003-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: lexer.m.
% main author: fjh.
% stability: high.
%
% Lexical analysis.  This module defines the representation of tokens
% and exports predicates for reading in tokens from an input stream.
%
% See ISO Prolog 6.4.  Also see the comments at the top of parser.m.
%
%--------------------------------------------------%

:- module lexer.
:- interface.
:- import_module io, char.

:- type	token
	--->	name(string)
	;	variable(string)
	;	integer(int)
	;	float(float)
	;	string(string)		% "...."
	;	open			% '('
	;	open_ct			% '(' without any preceding whitespace
	;	close			% ')'
	;	open_list		% '['
	;	close_list		% ']'
	;	open_curly		% '{'
	;	close_curly		% '}'
	;	ht_sep			% '|'
	;	comma			% ','
	;	end			% '.'
	;	junk(char)		% junk character in the input stream
	;	error(string)		% some other invalid token
	;	io_error(io__error)	% error reading from the input stream
	;	eof			% end-of-file
	;	integer_dot(int).	% the lexer will never return this.
					% The integer_dot/1 token is used
					% internally in the lexer, to keep
					% the grammar LL(1) so that only one
					% character of pushback is needed.
					% But the lexer will convert
					% integer_dot/1 tokens to integer/1
					% tokens before returning them.

% For every token, we record the line number of the line on
% which the token occurred.

:- type token_context == int.	% line number

% This "fat list" representation is more efficient than a list of pairs.
:- type token_list
	--->	token_cons(token, token_context, token_list)
	;	token_nil.

	% Read a list of tokens from the current input stream.
	% Keep reading until we encounter either an `end' token
	% (i.e. a full stop followed by whitespace) or the end-of-file.

:- pred lexer__get_token_list(token_list::out, io::di, io::uo) is det.

% The type `offset' represents a (zero-based) offset into a string.
:- type offset == int.

	% lexer__string_get_token_list(String, MaxOffset, Tokens,
	%		InitialPos, FinalPos):
	% Scan a list of tokens from a string,
	% starting at the current offset specified by InitialPos.
	% Keep scanning until either we encounter either an `end' token
	% (i.e. a full stop followed by whitespace) or until
	% we reach MaxOffset.  (MaxOffset must be =< the length of the string.)
	% Return the tokens scanned in Tokens, and return the position
	% one character past the end of the last token in FinalPos.

:- pred lexer__string_get_token_list(string::in, offset::in, token_list::out,
	posn::in, posn::out) is det.

	% lexer__string_get_token_list(String, Tokens, InitialPos, FinalPos):
	% calls string_get_token_list/5 above with MaxPos = length of String.
:- pred lexer__string_get_token_list(string::in, token_list::out,
	posn::in, posn::out) is det.

	% Convert a token to a human-readable string describing the token.
:- pred lexer__token_to_string(token::in, string::out) is det.

%--------------------------------------------------%


Node:library, Next:, Previous:lexer, Up:Top

32 library


%--------------------------------------------------%
% 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.
%--------------------------------------------------%
%
% This module imports all the modules in the Mercury library.
%
% It is used as a way for the Makefiles to know which library interface
% files, objects, etc., need to be installed.
%
% ---------------------------------------------------------------------------%
% ---------------------------------------------------------------------------%

:- module library.

:- interface.

:- pred library__version(string::out) is det.

%--------------------------------------------------%


Node:list, Next:, Previous:library, Up:Top

33 list


%--------------------------------------------------%
% 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.
%--------------------------------------------------%
%
% Module `list' - defines the list type, and various utility predicates
% that operate on lists.
%
% Authors: fjh, conway, trd, zs, philip, warwick, ...
% Stability: medium to high.
%
%--------------------------------------------------%

:- module list.
:- interface.
:- import_module int.

%--------------------------------------------------%

	% The definition of the type `list(T)':
	%	A list is either an empty list, denoted `[]',
	%	or an element `Head' of type `T' followed by a tail `Tail'
	%	of type `list(T)', denoted `[Head | Tail]'.
	%

:- type list(T) ---> [] ; [T | list(T)].

%--------------------------------------------------%

	% Some declarations for complicated modes using lists.
	% Partially instantiated mode aren't fully implemented yet,
	% so don't try to use these.

:- inst list_skel(I) = bound(([] ; [I | list_skel(I)])).
:- inst list_skel = list_skel(free).

:- inst non_empty_list = bound([ground | ground]).

:- mode in_list_skel :: list_skel -> list_skel.
:- mode out_list_skel :: free -> list_skel.
:- mode list_skel_out :: list_skel -> ground.

	% These more verbose versions are deprecated.
	% They exist only for backwards compatibility,
	% and will be removed in a future release.
:- mode input_list_skel :: in_list_skel.
:- mode output_list_skel :: out_list_skel.
:- mode list_skel_output :: list_skel_out.

	% These modes are particularly useful for passing around lists
	% of higher order terms, since they have complicated insts
	% which are not correctly approximated by "ground".
:- mode list_skel_in(I) :: list_skel(I) -> list_skel(I).
:- mode list_skel_out(I) :: free -> list_skel(I).

%--------------------------------------------------%

:- pred list__is_empty(list(T)::in) is semidet.

:- pred list__is_not_empty(list(T)::in) is semidet.

	% list__cons(X, Y, Z) <=> Z = [X | Y].
	%
:- pred list__cons(T, list(T), list(T)).
:- mode list__cons(in, in, out) is det.
:- func list__cons(T, list(T)) = list(T).

	% Standard append predicate:
	% list__append(Start, End, List) is true iff
	% `List' is the result of concatenating `Start' and `End'.
	%
:- pred list__append(list(T), list(T), list(T)).
:- mode list__append(di, di, uo) is det.
:- mode list__append(in, in, out) is det.
:- mode list__append(in, in, in) is semidet.	% implied
:- mode list__append(in, out, in) is semidet.
:- mode list__append(out, out, in) is multi.
%	The following mode is semidet in the sense that it doesn't
%	succeed more than once - but it does create a choice-point,
%	which means it's inefficient and that the compiler can't deduce
%	that it is semidet.  Use list__remove_suffix instead.
% :- mode list__append(out, in, in) is semidet.

:- func list__append(list(T), list(T)) = list(T).

	% associativity of append
:- promise all [A, B, C, ABC]
	(
		( some [AB]
			(list__append(A, B, AB), list__append(AB, C, ABC)) )
	<=>
		( some [BC]
			(list__append(B, C, BC), list__append(A, BC, ABC)) )
	).
	% construction equivalence law.
	% XXX when we implement rewrite rules, we should change this law
	% to a rewrite rule.
:- promise all [L, H, T] ( append([H], T, L) <=> L = [H | T] ).

	% L1 ++ L2 = L :- list__append(L1, L2, L).
	%
:- func list(T) ++ list(T) = list(T).

	% list__remove_suffix(List, Suffix, Prefix):
	%	The same as list__append(Prefix, Suffix, List) except that
	%	this is semidet whereas list__append(out, in, in) is nondet.
:- pred list__remove_suffix(list(T)::in, list(T)::in, list(T)::out) is semidet.

	% list__merge(L1, L2, L):
	%	L is the result of merging the elements of L1 and L2,
	%	in ascending order.  L1 and L2 must be sorted.
:- pred list__merge(list(T)::in, list(T)::in, list(T)::out) is det.
:- func list__merge(list(T), list(T)) = list(T).

	% list__merge_and_remove_dups(L1, L2, L):
	%	L is the result of merging the elements of L1 and L2,
	%	in ascending order, and eliminating any duplicates.
	%	L1 and L2 must be sorted and must each not contain any
	%	duplicates.
:- pred list__merge_and_remove_dups(list(T)::in, list(T)::in, list(T)::out)
	is det.
:- func list__merge_and_remove_dups(list(T), list(T)) = list(T).

	% list__remove_adjacent_dups(L0, L) :
	%	L is the result of replacing every sequence of duplicate
	%	elements in L0 with a single such element.
:- pred list__remove_adjacent_dups(list(T)::in, list(T)::out) is det.
:- func list__remove_adjacent_dups(list(T)) = list(T).

	% list__remove_dups(L0, L) :
	%	L is the result of deleting the second and subsequent
	%	occurrences of every element that occurs twice in L0.
:- pred list__remove_dups(list(T)::in, list(T)::out) is det.
:- func list__remove_dups(list(T)) = list(T).

	% list__member(Elem, List) :
	%	True iff `List' contains `Elem'.
:- pred list__member(T, list(T)).
:- mode list__member(in, in) is semidet.
:- mode list__member(out, in) is nondet.

	% list__member(Elem, List, SubList) :
	%	True iff `List' contains `Elem', and `SubList' is
	%	a suffix of `List' beginning with `Elem'.
	%	Same as `SubList = [Elem | _], list__append(_, SubList, List)'.
	%
:- pred list__member(T::out, list(T)::in, list(T)::out) is nondet.

	% list__length(List, Length) :
	%	True iff `Length' is the length of `List', i.e. if
	%	`List' contains `Length' elements.
	%
:- pred list__length(list(_T), int).
:- mode list__length(in, out) is det.
	% XXX The current mode checker can't handle this mode
% :- mode list__length(input_list_skel, out) is det.

:- func list__length(list(T)) = int.

	% list__same_length(ListA, ListB) :
	%	True iff `ListA' and `ListB' have the same length,
	%	i.e. iff they both contain the same number of elements.
	%
:- pred list__same_length(list(T1), list(T2)).
:- mode list__same_length(in, output_list_skel) is det.
:- mode list__same_length(output_list_skel, in) is det.
:- mode list__same_length(in, in) is semidet.
% XXX The current mode checker can't handle these modes
% :- mode list__same_length(input_list_skel, output_list_skel) is det.
% :- mode list__same_length(output_list_skel, input_list_skel) is det.

	% list__split_list(Len, List, Start, End):
	%	splits `List' into a prefix `Start' of length `Len',
	%	and a remainder `End'.
	%	See also: list__take, list__drop.
	%
:- pred list__split_list(int::in, list(T)::in, list(T)::out, list(T)::out)
	is semidet.

	% list__take(Len, List, Start):
	%	`Start' is the first `Len' elements of `List'.
	%	Fails if `List' has less than `Len' elements.
	%	See also: list__split_list.
	%
:- pred list__take(int::in, list(T)::in, list(T)::out) is semidet.

	% list__take_upto(Len, List, Start):
	%	`Start' is the first `Len' elements of `List'.
	%	If `List' has less than `Len' elements, return the entire list.
	%
:- pred list__take_upto(int::in, list(T)::in, list(T)::out) is det.
:- func list__take_upto(int, list(T)) = list(T).

	% list__drop(Len, List, End):
	%	`End' is the remainder of `List' after removing the
	%	first `Len' elements.
	%	See also: list__split_list.
	%
:- pred list__drop(int::in, list(T)::in, list(T)::out) is semidet.

	% list__insert(Elem, List0, List):
	%	`List' is the result of inserting `Elem' somewhere in `List0'.
	%	Same as `list__delete(List, Elem, List0)'.
	%
:- pred list__insert(T, list(T), list(T)).
:- mode list__insert(in, in, in) is semidet.
:- mode list__insert(in, out, in) is nondet.
:- mode list__insert(out, out, in) is nondet.
:- mode list__insert(in, in, out) is multi.

	% list__delete(List, Elem, Remainder):
	%	True iff `Elem' occurs in `List', and
	%	`Remainder' is the result of deleting one occurrence of
	%	`Elem' from `List'.
	%
:- pred list__delete(list(T), T, list(T)).
:- mode list__delete(in, in, in) is semidet.
:- mode list__delete(in, in, out) is nondet.
:- mode list__delete(in, out, out) is nondet.
:- mode list__delete(out, in, in) is multi.

:- func list__delete_all(list(T), T) = list(T).

	% list__delete_first(List0, Elem, List) is true iff Elem occurs in List0
	% and List is List0 with the first occurrence of Elem removed.
	%
:- pred list__delete_first(list(T)::in, T::in, list(T)::out) is semidet.

	% list__delete_all(List0, Elem, List) is true iff List is List0 with
	% all occurrences of Elem removed.
	%
:- pred list__delete_all(list(T), T, list(T)).
:- mode list__delete_all(di, in, uo) is det.
:- mode list__delete_all(in, in, out) is det.

	% list__delete_elems(List0, Elems, List) is true iff List is List0 with
	% all occurrences of all elements of Elems removed.
	%
:- pred list__delete_elems(list(T)::in, list(T)::in, list(T)::out) is det.
:- func list__delete_elems(list(T), list(T)) = list(T).

	% list__replace(List0, D, R, List) is true iff List is List0
	% with an occurrence of D replaced with R.
	%
:- pred list__replace(list(T), T, T, list(T)).
:- mode list__replace(in, in, in, in) is semidet.
:- mode list__replace(in, in, in, out) is nondet.

	% list__replace_first(List0, D, R, List) is true iff List is List0
	% with the first occurrence of D replaced with R.
	%
:- pred list__replace_first(list(T)::in, T::in, T::in, list(T)::out)
	is semidet.

	% list__replace_all(List0, D, R, List) is true iff List is List0
	% with all occurrences of D replaced with R.
	%
:- pred list__replace_all(list(T)::in, T::in, T::in, list(T)::out) is det.
:- func list__replace_all(list(T), T, T) = list(T).

	% list__replace_nth(List0, N, R, List) is true iff List is List0
	% with Nth element replaced with R.
	% Fails if N < 1 or if length of List0 < N.
	% (Position numbers start from 1.)
	%
:- pred list__replace_nth(list(T)::in, int::in, T::in, list(T)::out)
	is semidet.

	% list__replace_nth_det(List0, N, R, List) is true iff List is List0
	% with Nth element replaced with R.
	% Aborts if N < 1 or if length of List0 < N.
	% (Position numbers start from 1.)
	%
:- pred list__replace_nth_det(list(T)::in, int::in, T::in, list(T)::out)
	is det.
:- func list__replace_nth_det(list(T), int, T) = list(T).

	% list__sort_and_remove_dups(List0, List):
	%	List is List0 sorted with the second and subsequent
	%	occurrence of any duplicates removed.
	%
:- pred list__sort_and_remove_dups(list(T)::in, list(T)::out) is det.
:- func list__sort_and_remove_dups(list(T)) = list(T).

	% list__sort(List0, List):
	%	List is List0 sorted.
	%
:- pred list__sort(list(T)::in, list(T)::out) is det.
:- func list__sort(list(T)) = list(T).

	% list__reverse(List, Reverse):
	%	`Reverse' is a list containing the same elements as `List'
	%	but in reverse order.
	%
:- pred list__reverse(list(T)::in, list(T)::out) is det.
:- func list__reverse(list(T)) = list(T).

	% list__perm(List0, List):
	%	True iff `List' is a permutation of `List0'.
	%
:- pred	list__perm(list(T)::in, list(T)::out) is nondet.

	% list__nth_member_search(List, Elem, Position):
	%	Elem is the Position'th member of List.
	% 	(Position numbers start from 1.)
	%
:- pred list__nth_member_search(list(T)::in, T::in, int::out) is semidet.

	% list__index*(List, Position, Elem):
	%	These predicates select an element in a list from it's
	%	position.  The `index0' preds consider the first element
	%	element to be element number zero, whereas the `index1' preds
	%	consider the first element to be element number one.
	%	The `_det' preds call error/1 if the index is out of
	%	range, whereas the semidet preds fail if the index is out of
	%	range.
	%
:- pred list__index0(list(T)::in, int::in, T::out) is semidet.
:- pred list__index1(list(T)::in, int::in, T::out) is semidet.
:- pred list__index0_det(list(T)::in, int::in, T::out) is det.
:- pred list__index1_det(list(T)::in, int::in, T::out) is det.

:- func list__index0_det(list(T), int) = T.
:- func list__index1_det(list(T), int) = T.

	% list__zip(ListA, ListB, List):
	%	List is the result of alternating the elements
	%	of ListA and ListB, starting with the first element
	%	of ListA (followed by the first element of ListB,
	%	then the second element of listA, then the second
	%	element of ListB, etc.).  When there are no more
	%	elements remaining in one of the lists,
	% 	the remainder of the nonempty list is appended.
	%
:- pred list__zip(list(T)::in, list(T)::in, list(T)::out) is det.
:- func list__zip(list(T), list(T)) = list(T).

	% list__duplicate(Count, Elem, List) is true iff List is a list
	% containing Count duplicate copies of Elem.
	%
:- pred list__duplicate(int::in, T::in, list(T)::out) is det.
:- func list__duplicate(int, T) = list(T).

	% list__condense(ListOfLists, List):
	%	`List' is the result of concatenating all the
	%	elements of `ListOfLists'.
	%
:- pred list__condense(list(list(T))::in, list(T)::out) is det.
:- func list__condense(list(list(T))) = list(T).

	% list__chunk(List, ChunkSize, Chunks):
	%	Takes a list `List' and breaks it into a list of lists `Chunks',
	%	such that the length of each list in `Chunks' is at most
	%	`ChunkSize.  (More precisely, the length of each list in
	%	`Chunks' other than the last one is exactly `ChunkSize',
	%	and the length of the last list in `Chunks' is between one
	%	and `ChunkSize'.)
	%
:- pred list__chunk(list(T)::in, int::in, list(list(T))::out) is det.
:- func list__chunk(list(T), int) = list(list(T)).

	% list__sublist(SubList, FullList) is true
	%	if one can obtain SubList by starting with FullList
	%	and deleting some of its elements.
:- pred list__sublist(list(T)::in, list(T)::in) is semidet.

	% list__all_same(List) is true
	% 	if all elements of the list are the same
:- pred list__all_same(list(T)::in) is semidet.

	% list__last(List, Last) is true
	%	if Last is the last element of List.
:- pred list__last(list(T)::in, T::out) is semidet.

	% A deterministic version of list__last, which aborts instead of
	% failing if the input list is empty.
:- pred list__last_det(list(T)::in, T::out) is det.

	% list__split_last(List, AllButLast, Last) is true
	%	if Last is the last element of List and AllButLast is the list
	%	of elements before it.
:- pred list__split_last(list(T)::in, list(T)::out, T::out) is semidet.

	% A deterministic version of list__split_last, which aborts instead of
	% failing if the input list is empty.
:- pred list__split_last_det(list(T)::in, list(T)::out, T::out) is det.

%--------------------------------------------------%
%
% The following group of predicates use higher-order terms to simplify
% various list processing tasks. They implement pretty much standard
% sorts of operations provided by standard libraries for functional languages.
%
%--------------------------------------------------%

	% list__map(T, L, M) uses the closure T
	% to transform the elements of L into the elements of M.
:- pred list__map(pred(X, Y), list(X), list(Y)).
:- mode list__map(pred(in, out) is det, in, out) is det.
:- mode list__map(pred(in, out) is cc_multi, in, out) is cc_multi.
:- mode list__map(pred(in, out) is semidet, in, out) is semidet.
:- mode list__map(pred(in, out) is multi, in, out) is multi.
:- mode list__map(pred(in, out) is nondet, in, out) is nondet.
:- mode list__map(pred(in, in) is semidet, in, in) is semidet.

:- func list__map(func(X) = Y, list(X)) = list(Y).

	% list__map2(T, L, M1, M2) uses the closure T
	% to transform the elements of L into the elements of M1 and M2.
:- pred list__map2(pred(A, B, C), list(A), list(B), list(C)).
:- mode list__map2(pred(in, out, out) is det, in, out, out) is det.
:- mode list__map2(pred(in, out, out) is semidet, in, out, out) is semidet.
:- mode list__map2(pred(in, out, out) is multi, in, out, out) is multi.
:- mode list__map2(pred(in, out, out) is nondet, in, out, out) is nondet.
:- mode list__map2(pred(in, in, in) is semidet, in, in, in) is semidet.

	% list__map3(T, L, M1, M2, M3) uses the closure T
	% to transform the elements of L into the elements of M1, M2 and M3.
:- pred list__map3(pred(A, B, C, D), list(A), list(B), list(C), list(D)).
:- mode list__map3(pred(in, out, out, out) is det, in, out, out, out) is det.
:- mode list__map3(pred(in, out, out, out) is semidet, in, out, out, out)
	is semidet.
:- mode list__map3(pred(in, out, out, out) is multi, in, out, out, out)
	is multi.
:- mode list__map3(pred(in, out, out, out) is nondet, in, out, out, out)
	is nondet.
:- mode list__map3(pred(in, in, in, in) is semidet, in, in, in, in) is semidet.

	% list__map_corresponding(F, [A1, .. An], [B1, .. Bn]) =
	% 	[F(A1, B1), .., F(An, Bn)].
	%
	% An exception is raised if the list arguments differ in length.
	%
:- func list__map_corresponding(func(A, B) = C, list(A), list(B)) = list(C).

	% list__map_corresponding3(F, [A1, .. An], [B1, .. Bn], [C1, .. Cn]) =
	% 	[F(A1, B1, C1), .., F(An, Bn, Cn)].
	%
	% An exception is raised if the list arguments differ in length.
	%
:- func list__map_corresponding3(func(A, B, C) = D, list(A), list(B), list(C))
	= list(D).

	% list__filter_map_corresponding/3 is like list__map_corresponding/3
	% except the function argument is semidet and the output list
	% consists of only those applications of the function argument that
	% succeeded.
	%
:- func list__filter_map_corresponding(func(A, B) = C, list(A), list(B))
	= list(C).
:- mode list__filter_map_corresponding(func(in, in) = out is semidet, in, in)
	= out is det.

	% list__filter_map_corresponding3/4 is like list__map_corresponding3/4
	% except the function argument is semidet and the output list
	% consists of only those applications of the function argument that
	% succeeded.
	%
:- func list__filter_map_corresponding3(func(A, B, C) = D,
	list(A), list(B), list(C)) = list(D).
:- mode list__filter_map_corresponding3(func(in, in, in) = out is semidet,
	in, in, in) = out is det.

	% list__foldl(Pred, List, Start, End) calls Pred with each
	% element of List (working left-to-right) and an accumulator
	% (with the initial value of Start), and returns the final
	% value in End.
:- pred list__foldl(pred(X, Y, Y), list(X), Y, Y).
:- mode list__foldl(pred(in, di, uo) is det, in, di, uo) is det.
:- mode list__foldl(pred(in, in, out) is det, in, in, out) is det.
:- mode list__foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode list__foldl(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode list__foldl(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
:- mode list__foldl(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.

:- func list__foldl(func(X, Y) = Y, list(X), Y) = Y.

	% list__foldr(Pred, List, Start, End) calls Pred with each
	% element of List (working right-to-left) and an accumulator
	% (with the initial value of Start), and returns the final
	% value in End.
:- pred list__foldr(pred(X, Y, Y), list(X), Y, Y).
:- mode list__foldr(pred(in, in, out) is det, in, in, out) is det.
:- mode list__foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode list__foldr(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode list__foldr(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
:- mode list__foldr(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.

:- func list__foldr(func(X, Y) = Y, list(X), Y) = Y.

	% list__foldl2(Pred, List, !Acc1, !Acc2)
	% Does the same job as list__foldl, but with two accumulators.
	% (Although no more expressive than list__foldl, this is often
	% a more convenient format, and a little more efficient).
:- pred list__foldl2(pred(X, Y, Y, Z, Z), list(X), Y, Y, Z, Z).
:- mode list__foldl2(pred(in, in, out, in, out) is det,
	in, in, out, in, out) is det.
:- mode list__foldl2(pred(in, in, out, in, out) is semidet,
	in, in, out, in, out) is semidet.
:- mode list__foldl2(pred(in, in, out, in, out) is nondet,
	in, in, out, in, out) is nondet.
:- mode list__foldl2(pred(in, in, out, mdi, muo) is det,
	in, in, out, mdi, muo) is det.
:- mode list__foldl2(pred(in, in, out, di, uo) is det,
	in, in, out, di, uo) is det.
:- mode list__foldl2(pred(in, di, uo, di, uo) is det,
	in, di, uo, di, uo) is det.

	% list__foldl3(Pred, List, !Acc1, !Acc2, !Acc3)
	% Does the same job as list__foldl, but with two accumulators.
	% (Although no more expressive than list__foldl, this is often
	% a more convenient format, and a little more efficient).
:- pred list__foldl3(pred(L, A1, A1, A2, A2, A3, A3), list(L),
	A1, A1, A2, A2, A3, A3).
:- mode list__foldl3(pred(in, in, out, in, out, in, out) is det,
	in, in, out, in, out, in, out) is det.
:- mode list__foldl3(pred(in, in, out, in, out, in, out) is semidet,
	in, in, out, in, out, in, out) is semidet.
:- mode list__foldl3(pred(in, in, out, in, out, in, out) is nondet,
	in, in, out, in, out, in, out) is nondet.
:- mode list__foldl3(pred(in, in, out, in, out, di, uo) is det,
	in, in, out, in, out, di, uo) is det.

	% list__foldl4(Pred, List, !Acc1, !Acc2, !Acc3, !Acc4)
	% Does the same job as list__foldl, but with two accumulators.
	% (Although no more expressive than list__foldl, this is often
	% a more convenient format, and a little more efficient).
:- pred list__foldl4(pred(L, A1, A1, A2, A2, A3, A3, A4, A4), list(L),
	A1, A1, A2, A2, A3, A3, A4, A4).
:- mode list__foldl4(pred(in, in, out, in, out, in, out, in, out) is det,
	in, in, out, in, out, in, out, in, out) is det.
:- mode list__foldl4(pred(in, in, out, in, out, in, out, in, out) is semidet,
	in, in, out, in, out, in, out, in, out) is semidet.
:- mode list__foldl4(pred(in, in, out, in, out, in, out, in, out) is nondet,
	in, in, out, in, out, in, out, in, out) is nondet.
:- mode list__foldl4(pred(in, in, out, in, out, in, out, di, uo) is det,
	in, in, out, in, out, in, out, di, uo) is det.

	% list__map_foldl(Pred, InList, OutList, Start, End) calls Pred
	% with an accumulator (with the initial value of Start) on
	% each element of InList (working left-to-right) to transform
	% InList into OutList.  The final value of the accumulator is
	% returned in End.
:- pred list__map_foldl(pred(X, Y, Z, Z), list(X), list(Y), Z, Z).
:- mode list__map_foldl(pred(in, out, di, uo) is det, in, out, di, uo)
	is det.
:- mode list__map_foldl(pred(in, out, in, out) is det, in, out, in, out)
	is det.
:- mode list__map_foldl(pred(in, out, in, out) is semidet, in, out, in, out)
	is semidet.
:- mode list__map_foldl(pred(in, out, in, out) is nondet, in, out, in, out)
	is nondet.

	% Same as list__map_foldl, but with two mapped outputs.
:- pred list__map2_foldl(pred(X, Y1, Y2, Z, Z), list(X), list(Y1), list(Y2),
	Z, Z).
:- mode list__map2_foldl(pred(in, out, out, di, uo) is det, in, out, out,
	di, uo) is det.
:- mode list__map2_foldl(pred(in, out, out, in, out) is det, in, out, out,
	in, out) is det.
:- mode list__map2_foldl(pred(in, out, out, in, out) is semidet, in, out, out,
	in, out) is semidet.
:- mode list__map2_foldl(pred(in, out, out, in, out) is nondet, in, out, out,
	in, out) is nondet.

	% Same as list__map_foldl, but with two accumulators.
:- pred list__map_foldl2(pred(X, Y, A, A, B, B), list(X), list(Y), A, A, B, B).
:- mode list__map_foldl2(pred(in, out, in, out, di, uo) is det,
	in, out, in, out, di, uo) is det.
:- mode list__map_foldl2(pred(in, out, in, out, in, out) is det,
	in, out, in, out, in, out) is det.
:- mode list__map_foldl2(pred(in, out, in, out, in, out) is semidet,
	in, out, in, out, in, out) is semidet.
:- mode list__map_foldl2(pred(in, out, in, out, in, out) is nondet,
	in, out, in, out, in, out) is nondet.

	% Same as list__map_foldl, but with three accumulators.
:- pred list__map_foldl3(pred(X, Y, A, A, B, B, C, C), list(X), list(Y),
	A, A, B, B, C, C).
:- mode list__map_foldl3(pred(in, out, in, out, in, out, di, uo) is det,
	in, out, in, out, in, out, di, uo) is det.
:- mode list__map_foldl3(pred(in, out, in, out, in, out, in, out) is det,
	in, out, in, out, in, out, in, out) is det.
:- mode list__map_foldl3(pred(in, out, in, out, in, out, in, out) is semidet,
	in, out, in, out, in, out, in, out) is semidet.
:- mode list__map_foldl3(pred(in, out, in, out, in, out, in, out) is nondet,
	in, out, in, out, in, out, in, out) is nondet.

	% list__filter(Pred, List, TrueList) takes a closure with one
	% input argument and for each member of List `X', calls the closure.
	% Iff call(Pred, X) is true, then X is included in TrueList.
:- pred list__filter(pred(X)::in(pred(in) is semidet), list(X)::in,
	list(X)::out) is det.
:- func list__filter(pred(X)::in(pred(in) is semidet), list(X)::in)
	= (list(X)::out) is det.

	% list__filter(Pred, List, TrueList, FalseList) takes a closure with one
	% input argument and for each member of List `X', calls the closure.
	% Iff call(Pred, X) is true, then X is included in TrueList.
	% Iff call(Pred, X) is false, then X is included in FalseList.
:- pred list__filter(pred(X)::in(pred(in) is semidet), list(X)::in,
	list(X)::out, list(X)::out) is det.

	% list__filter_map(Transformer, List, TrueList) takes a predicate
	% with one input argument and one output argument. It is called
	% with each element of List. If a call succeeds, then the output is
	% included in TrueList.
:- pred list__filter_map(pred(X, Y)::in(pred(in, out) is semidet),
	list(X)::in, list(Y)::out) is det.

:- func list__filter_map(func(X) = Y, list(X)) = list(Y).
:- mode list__filter_map(func(in) = out is semidet, in) = out is det.

	% list__filter_map(Transformer, List, TrueList, FalseList) takes
	% a predicate with one input argument and one output argument.
	% It is called with each element of List. If a call succeeds,
	% then the output is included in TrueList; otherwise, the failing
	% input is included in FalseList.
:- pred list__filter_map(pred(X, Y)::in(pred(in, out) is semidet),
	list(X)::in, list(Y)::out, list(X)::out) is det.

	% list__takewhile(Predicate, List, UptoList, AfterList) takes a
	% closure with one input argument, and calls it on successive members
	% of List as long as the calls succeed. The elements for which
	% the call succeeds are placed in UptoList and the first element for
	% which the call fails, and all the remaining elements of List are
	% placed in AfterList.
:- pred list__takewhile(pred(T)::in(pred(in) is semidet), list(T)::in,
	list(T)::out, list(T)::out) is det.

%--------------------------------------------------%

	% list__sort(Compare, Unsorted, Sorted) is true iff Sorted is a
	% list containing the same elements as Unsorted, where Sorted is
	% sorted with respect to the ordering defined by the predicate
	% term Compare, and the elements that are equivalent in this ordering
	% appear in the same sequence in Sorted as they do in Unsorted
	% (that is, the sort is stable).
:- pred list__sort(comparison_pred(X)::in(comparison_pred), list(X)::in,
	list(X)::out) is det.
:- func list__sort(comparison_func(X), list(X)) = list(X).

	% list__sort_and_remove_dups(Compare, Unsorted, Sorted) is true iff
	% Sorted is a list containing the same elements as Unsorted, where
	% Sorted is sorted with respect to the ordering defined by the
	% predicate term Compare, except that if two elements in Unsorted
	% are equivalent with respect to this ordering only the one which
	% occurs first will be in Sorted.
:- pred list__sort_and_remove_dups(comparison_pred(X)::in(comparison_pred),
	list(X)::in, list(X)::out) is det.

	% list__remove_adjacent_dups(P, L0, L) is true iff L is the result
	% of replacing every sequence of elements in L0 which are equivalent
	% with respect to the ordering, with the first occurrence in L0 of
	% such an element.
:- pred list__remove_adjacent_dups(comparison_pred(X)::in(comparison_pred),
	list(X)::in, list(X)::out) is det.

	% list__merge(Compare, As, Bs, Sorted) is true iff, assuming As and
	% Bs are sorted with respect to the ordering defined by Compare,
	% Sorted is a list containing the elements of As and Bs which is
	% also sorted.  For elements which are equivalent in the ordering,
	% if they come from the same list then they appear in the same
	% sequence in Sorted as they do in that list, otherwise the elements
	% from As appear before the elements from Bs.
:- pred list__merge(comparison_pred(X)::in(comparison_pred),
	list(X)::in, list(X)::in, list(X)::out) is det.

:- func list__merge(comparison_func(X), list(X), list(X)) = list(X).

	% list__merge_and_remove_dups(P, As, Bs, Sorted) is true iff, assuming
	% As and Bs are sorted with respect to the ordering defined by
	% Compare and neither contains any duplicates, Sorted is a list
	% containing the elements of As and Bs which is also sorted and
	% contains no duplicates.  If an element from As is duplicated in
	% Bs (that is, they are equivalent in the ordering), then the element
	% from As is the one that appears in Sorted.
:- pred list__merge_and_remove_dups(comparison_pred(X)::in(comparison_pred),
	list(X)::in, list(X)::in, list(X)::out) is det.

:- func list__merge_and_remove_dups(comparison_func(X), list(X), list(X))
	= list(X).

%--------------------------------------------------%

	% list__series(X, OK, Succ) = [X0, X1, ..., Xn]
	% 	where X0 = X and successive elements Xj, Xk
	% 	are computed as Xk = Succ(Xj).  The series
	% 	terminates as soon as an element Xi is
	% 	generated such that OK(Xi) fails; Xi is not
	% 	included in the output.
	%
:- func list__series(T, pred(T), func(T) = T) = list(T).
:- mode list__series(in, pred(in) is semidet, func(in) = out is det) = out
	is det.

% ---------------------------------------------------------------------------- %

	% Lo `..` Hi = [Lo, Lo + 1, ..., Hi] if Lo =< Hi
	%            =                    [] otherwise
	%
:- func int `..` int = list(int).

%--------------------------------------------------%

	% list__det_head(List) returns the first element of List,
	% calling error/1 if List is empty.
:- func list__det_head(list(T)) = T.

	% list__det_tail(List) returns the tail of List,
	% calling error/1 if List is empty.
:- func list__det_tail(list(T)) = list(T).

% ---------------------------------------------------------------------------- %
% ---------------------------------------------------------------------------- %


Node:map, Next:, Previous:list, Up:Top

34 map


%--------------------------------------------------%
% 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).

%--------------------------------------------------%


Node:math, Next:, Previous:map, Up:Top

35 math


%--------------------------------------------------%
% Copyright (C) 1995-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: math.m
% Main author: bromage
% Stability: high
%
% Higher mathematical operations.  (The basics are in float.m.)
%
% By default, domain errors are currently handled by throwing an exception.
%
% For better performance, it is possible to disable the Mercury domain
% checking by compiling with `--intermodule-optimization' and the C macro
% symbol `ML_OMIT_MATH_DOMAIN_CHECKS' defined, e.g. by using
% `MCFLAGS=--intermodule-optimization' and
% `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS' in your Mmakefile,
% or by compiling with the command
% `mmc --intermodule-optimization --cflags -DML_OMIT_MATH_DOMAIN_CHECKS'.
%
% For maximum performance, all Mercury domain checking can be disabled by
% recompiling this module using `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS'
% or `mmc --cflags -DML_OMIT_MATH_DOMAIN_CHECKS' as above. You can
% either recompile the entire library, or just copy `math.m' to your
% application's source directory and link with it directly instead of as
% part of the library.
%
% Note that the above performance improvements are semantically safe,
% since the C math library and/or floating point hardware perform these
% checks for you.  The benefit of having the Mercury library perform the
% checks instead is that Mercury will tell you in which function or
% predicate the error occurred, as well as giving you a stack trace if
% that is enabled; with the checks disabled you only have the information
% that the floating-point exception signal handler gives you.
%
%--------------------------------------------------%

:- module math.
:- interface.

%--------------------------------------------------%
% Mathematical constants

	% Pythagoras' number
:- func math__pi = float.

	% Base of natural logarithms
:- func math__e = float.

%--------------------------------------------------%
% "Next integer" operations

	% math__ceiling(X) = Ceil is true if Ceil is the smallest integer
	% not less than X.
:- func math__ceiling(float) = float.

	% math__floor(X) = Floor is true if Floor is the largest integer
	% not greater than X.
:- func math__floor(float) = float.

	% math__round(X) = Round is true if Round is the integer
	% closest to X.  If X has a fractional value of 0.5, it
	% is rounded up.
:- func math__round(float) = float.

	% math__truncate(X) = Trunc is true if Trunc is the integer
	% closest to X such that |Trunc| =< |X|.
:- func math__truncate(float) = float.

%--------------------------------------------------%
% Polynomial roots

	% math__sqrt(X) = Sqrt is true if Sqrt is the positive square
	% root of X.
	%
	% Domain restriction: X >= 0
:- func math__sqrt(float) = float.

:- type math__quadratic_roots
	--->	no_roots
	;	one_root(float)
	;	two_roots(float, float).

	% math__solve_quadratic(A, B, C) = Roots is true if Roots are
	% the solutions to the equation Ax^2 + Bx + C.
	%
	% Domain restriction: A \= 0
:- func math__solve_quadratic(float, float, float) = quadratic_roots.

%--------------------------------------------------%
% Power/logarithm operations

	% math__pow(X, Y) = Res is true if Res is X raised to the
	% power of Y.
	%
	% Domain restriction: X >= 0 and (X = 0 implies Y > 0)
:- func math__pow(float, float) = float.

	% math__exp(X) = Exp is true if Exp is e raised to the
	% power of X.
:- func math__exp(float) = float.

	% math__ln(X) = Log is true if Log is the natural logarithm
	% of X.
	%
	% Domain restriction: X > 0
:- func math__ln(float) = float.

	% math__log10(X) = Log is true if Log is the logarithm to
	% base 10 of X.
	%
	% Domain restriction: X > 0
:- func math__log10(float) = float.

	% math__log2(X) = Log is true if Log is the logarithm to
	% base 2 of X.
	%
	% Domain restriction: X > 0
:- func math__log2(float) = float.

	% math__log(B, X) = Log is true if Log is the logarithm to
	% base B of X.
	%
	% Domain restriction: X > 0 and B > 0 and B \= 1
:- func math__log(float, float) = float.

%--------------------------------------------------%
% Trigonometric operations

	% math__sin(X) = Sin is true if Sin is the sine of X.
:- func math__sin(float) = float.

	% math__cos(X) = Cos is true if Cos is the cosine of X.
:- func math__cos(float) = float.

	% math__tan(X) = Tan is true if Tan is the tangent of X.
:- func math__tan(float) = float.

	% math__asin(X) = ASin is true if ASin is the inverse
	% sine of X, where ASin is in the range [-pi/2,pi/2].
	%
	% Domain restriction: X must be in the range [-1,1]
:- func math__asin(float) = float.

	% math__acos(X) = ACos is true if ACos is the inverse
	% cosine of X, where ACos is in the range [0, pi].
	%
	% Domain restriction: X must be in the range [-1,1]
:- func math__acos(float) = float.

	% math__atan(X) = ATan is true if ATan is the inverse
	% tangent of X, where ATan is in the range [-pi/2,pi/2].
:- func math__atan(float) = float.

	% math__atan2(Y, X) = ATan is true if ATan is the inverse
	% tangent of Y/X, where ATan is in the range [-pi,pi].
:- func math__atan2(float, float) = float.

%--------------------------------------------------%
% Hyperbolic functions

	% math__sinh(X) = Sinh is true if Sinh is the hyperbolic
	% sine of X.
:- func math__sinh(float) = float.

	% math__cosh(X) = Cosh is true if Cosh is the hyperbolic
	% cosine of X.
:- func math__cosh(float) = float.

	% math__tanh(X) = Tanh is true if Tanh is the hyperbolic
	% tangent of X.
:- func math__tanh(float) = float.

	% A domain error exception, indicates that the inputs to a function
	% were outside the domain of the function.  The string indicates
	% where the error occurred.
	%
	% It is possible to switch domain checking off, in which case,
	% depending on the backend, a domain error may cause a program
	% abort.

:- type domain_error ---> domain_error(string).

%--------------------------------------------------%
%--------------------------------------------------%


Node:multi_map, Next:, Previous:math, Up:Top

36 multi_map


%--------------------------------------------------%
% Copyright (C) 1995, 1997, 2000, 2002-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: multi_map.m.
% Main author: dylan.  Based on map.m, by fjh, conway.
% Stability: low.
%
% This file provides the 'multi_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.  A multi_map is similar, though allows a one to many relationship
% between keys and data.
%
% This is implemented almost as a special case of map.m.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module multi_map.
:- interface.
:- import_module map, list, assoc_list, set.

%--------------------------------------------------%

:- type multi_map(Key, Data)	==	map(Key, list(Data)).

%--------------------------------------------------%

	% Initialize an empty multi_map.
:- pred multi_map__init(multi_map(_, _)::uo) is det.
:- func multi_map__init = multi_map(_, _).

	% Check whether a multi_map is empty.
:- pred multi_map__is_empty(multi_map(_, _)::in) is semidet.

	% Check whether multi_map contains key
:- pred multi_map__contains(multi_map(K, _V)::in, K::in) is semidet.

:- pred multi_map__member(multi_map(K, V)::in, K::out, V::out) is nondet.

	% Search multi_map for given key.
:- pred multi_map__search(multi_map(K, V)::in, K::in, list(V)::out) is semidet.

	% Search multi_map for given key.
:- pred multi_map__nondet_search(multi_map(K, V)::in, K::in, V::out) is nondet.

	% Search multi_map for key, but abort if search fails.
:- pred multi_map__lookup(multi_map(K, V)::in, K::in, list(V)::out) is det.
:- func multi_map__lookup(multi_map(K, V), K) = list(V).

	% Search multi_map for key.
:- pred multi_map__nondet_lookup(multi_map(K, V)::in, K::in, V::out) is nondet.

	% Search multi_map for data.
:- pred multi_map__inverse_search(multi_map(K, V)::in, V::in, K::out) is nondet.

	% Insert a new key and corresponding value into a multi_map.
	% Fail if the key already exists.
:- pred multi_map__insert(multi_map(K, V)::in, K::in, V::in,
	multi_map(K, V)::out) is semidet.

	% Insert a new key and corresponding value into a multi_map.
	% Abort if the key already exists.
:- pred multi_map__det_insert(multi_map(K, V)::in, K::in, V::in,
	multi_map(K, V)::out) is det.
:- func multi_map__det_insert(multi_map(K, V), K, V) = multi_map(K, V).

	% Update (add) the value corresponding to a given key
	% Fail if the key doesn't already exist.
:- pred multi_map__update(multi_map(K, V)::in, K::in, V::in,
	multi_map(K, V)::out) is semidet.

	% Update (add) the value corresponding to a given key
	% Abort if the key doesn't already exist.
:- pred multi_map__det_update(multi_map(K, V)::in, K::in, V::in,
	multi_map(K, V)::out) is det.
:- func multi_map__det_update(multi_map(K, V), K, V) = multi_map(K, V).

	% Update (replace) the value corresponding to a given key
	% Abort if the key doesn't already exist.
:- pred multi_map__det_replace(multi_map(K, V)::in, K::in, list(V)::in,
	multi_map(K, V)::out) is det.
:- func multi_map__det_replace(multi_map(K, V), K, list(V)) = multi_map(K, V).

	% Update (add) value if the key is already present, otherwise
	% insert new key and value.
:- pred multi_map__set(multi_map(K, V)::in, K::in, V::in, multi_map(K, V)::out)
	is det.
:- func multi_map__set(multi_map(K, V), K, V) = multi_map(K, V).

	% Given a multi_map, return a list of all the keys in the multi_map
:- pred multi_map__keys(multi_map(K, _V)::in, list(K)::out) is det.
:- func multi_map__keys(multi_map(K, _V)) = list(K).

	% Given a multi_map, return a list of all the data values in the
	% multi_map
:- pred multi_map__values(multi_map(_K, V)::in, list(V)::out) is det.
:- func multi_map__values(multi_map(_K, V)) = list(V).

	% convert a multi_map to an association list
:- pred multi_map__to_flat_assoc_list(multi_map(K, V)::in,
	assoc_list(K, V)::out) is det.
:- func multi_map__to_flat_assoc_list(multi_map(K, V)) = assoc_list(K, V).

	% convert an association list to a multi_map
:- pred multi_map__from_flat_assoc_list(assoc_list(K, V)::in,
	multi_map(K, V)::out) is det.
:- func multi_map__from_flat_assoc_list(assoc_list(K, V)) = multi_map(K, V).

	% convert a multi_map to an association list, with all the
	% values for each key in one element of the association list.
:- pred multi_map__to_assoc_list(multi_map(K, V)::in,
	assoc_list(K, list(V))::out) is det.
:- func multi_map__to_assoc_list(multi_map(K, V)) = assoc_list(K, list(V)).

	% convert an association list with all the values for each
	% key in one element of the list to a multi_map
:- pred multi_map__from_assoc_list(assoc_list(K, list(V))::in,
	multi_map(K, V)::out) is det.
:- func multi_map__from_assoc_list(assoc_list(K, list(V))) = multi_map(K, V).

	% convert a sorted association list to a multi_map
:- pred multi_map__from_sorted_assoc_list(assoc_list(K, list(V))::in,
	multi_map(K, V)::out) is det.
:- func multi_map__from_sorted_assoc_list(assoc_list(K, list(V)))
	= multi_map(K, V).

	% delete a key and data from a multi_map
	% if the key is not present, leave the multi_map unchanged
:- pred multi_map__delete(multi_map(K, V)::in, K::in, multi_map(K, V)::out)
	is det.
:- func multi_map__delete(multi_map(K, V), K) = multi_map(K, V).

	% delete a data value from a key in a multi_map
	% if the key is not present, leave the multi_map unchanged
:- pred multi_map__delete(multi_map(K, V)::in, K::in, V::in,
	multi_map(K, V)::out) is det.
:- func multi_map__delete(multi_map(K, V), K, V) = multi_map(K, V).

	% delete a key-value pair from a multi_map and return the value.
	% fail if the key is not present
:- pred multi_map__remove(multi_map(K, V)::in, K::in, list(V)::out,
	multi_map(K, V)::out) is semidet.

	% delete a key-value pair from a multi_map and return the value.
	% abort if the key is not present
:- pred multi_map__det_remove(multi_map(K, V)::in, K::in, list(V)::out,
	multi_map(K, V)::out) is det.

	% Count the number of elements (keys) in the multi_map.
:- pred multi_map__count(multi_map(K, V)::in, int::out) is det.
:- func multi_map__count(multi_map(K, V)) = int.

	% Count the number of data elements in the multi_map.
:- pred multi_map__all_count(multi_map(K, V)::in, int::out) is det.
:- func multi_map__all_count(multi_map(K, V)) = int.

	% Convert a pair of lists (which must be of the same length)
	% to a multi_map.
:- pred multi_map__from_corresponding_lists(list(K)::in, list(V)::in,
	multi_map(K, V)::out) is det.
:- func multi_map__from_corresponding_lists(list(K), list(V))
	= multi_map(K, V).

	% Convert a pair of lists (which must be of the same length)
	% to a multi_map.
:- pred multi_map__from_corresponding_list_lists(list(K)::in, list(list(V))::in,
	multi_map(K, V)::out) is det.
:- func multi_map__from_corresponding_list_lists(list(K), list(list(V)))
	= multi_map(K, V).

	% For multi_map__merge(MultiMapA, MultiMapB, MultiMap).
:- pred multi_map__merge(multi_map(K, V)::in, multi_map(K, V)::in,
	multi_map(K, V)::out) is det.
:- func multi_map__merge(multi_map(K, V), multi_map(K, V))
	= multi_map(K, V).

	% multi_map__select takes a multi_map and a set of keys and returns
	% a multi_map containing the keys in the set and their corresponding
	% values.
:- pred multi_map__select(multi_map(K, V)::in, set(K)::in,
	multi_map(K, V)::out) is det.
:- func multi_map__select(multi_map(K, V), set(K)) = multi_map(K, V).

	% Given a list of keys, produce a list of their values in a
	% specified multi_map.
:- pred multi_map__apply_to_list(list(K)::in, multi_map(K, V)::in,
	list(V)::out) is det.
:- func multi_map__apply_to_list(list(K), multi_map(K, V)) = list(V).

	% Declaratively, a NOP.
	% Operationally, a suggestion that the implemention
	% optimize the representation of the multi_map in the expectation
	% of a number of lookups but few or no modifications.
:- pred multi_map__optimize(multi_map(K, V)::in, multi_map(K, V)::out) is det.
:- func multi_map__optimize(multi_map(K, V)) = multi_map(K, V).

	% Remove the smallest item from the multi_map, fail if
	% the multi_map is empty.
:- pred multi_map__remove_smallest(multi_map(K, V)::in, K::out, list(V)::out,
	multi_map(K, V)::out) is semidet.

%--------------------------------------------------%
%--------------------------------------------------%


Node:ops, Next:, Previous:multi_map, Up:Top

37 ops


%--------------------------------------------------%
% Copyright (C) 1995-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: ops.m.
% main author: fjh.
% stability: low.
%
% This module exports a typeclass `ops__op_table' which is used to define
% operator precedence tables for use by `parser__read_term_with_op_table'
% and `term_io__write_term_with_op_table'.
%
% It also exports an instance `ops__mercury_op_table' which implements the
% Mercury operator table defined in the Mercury Language Reference Manual.
%
% See samples/calculator2.m for an example program.
%
% XXX In the current implementation the table of Mercury operators
% is fixed and cannot be modified at run-time.
%
%--------------------------------------------------%

:- module ops.
:- interface.

:- typeclass ops__op_table(Table) where [

		% Check whether a string is the name of an infix operator,
		% and if it is, return its precedence and associativity.
	pred ops__lookup_infix_op(Table::in, string::in, ops__priority::out,
		ops__assoc::out, ops__assoc::out) is semidet,

		% Operator terms are terms of the form `X `Op` Y',
		% where `Op' is a variable or a name and `X' and `Y'
		% are terms. If operator terms are included in `Table',
		% return their precedence and associativity.
	pred ops__lookup_operator_term(Table::in, ops__priority::out,
		ops__assoc::out, ops__assoc::out) is semidet,

		% Check whether a string is the name of a prefix operator,
		% and if it is, return its precedence and associativity.
	pred ops__lookup_prefix_op(Table::in, string::in,
		ops__priority::out, ops__assoc::out) is semidet,

		% Check whether a string is the name of a binary prefix
		% operator, and if it is, return its precedence and
		% associativity.
	pred ops__lookup_binary_prefix_op(Table::in, string::in,
		ops__priority::out, ops__assoc::out, ops__assoc::out)
		is semidet,

		% Check whether a string is the name of a postfix operator,
		% and if it is, return its precedence and associativity.
	pred ops__lookup_postfix_op(Table::in, string::in, ops__priority::out,
		ops__assoc::out) is semidet,

		% Check whether a string is the name of an operator
	pred ops__lookup_op(Table::in, string::in) is semidet,

		% Returns the highest priority number (the lowest is zero).
	func ops__max_priority(Table) = ops__priority,

		% The maximum priority of an operator appearing
		% as the top-level functor of an argument of a compound
		% term.
		%
		% This will generally be the precendence of `,/2' less one.
		% If `,/2' does not appear in the op_table,
		% `ops__max_priority' plus one may be a reasonable value.
	func ops__arg_priority(Table) = ops__priority
].

%--------------------------------------------------%

	% The table of Mercury operators.
	% See the "Builtin Operators" section of the "Syntax" chapter
	% of the Mercury Language Reference Manual for details.
:- type ops__mercury_op_table.
:- instance ops__op_table(ops__mercury_op_table).

:- func ops__init_mercury_op_table = (ops__mercury_op_table::uo) is det.

%--------------------------------------------------%

	% Operators with a low "priority" bind more tightly than those
	% with a high "priority". For example, given that `+' has
	% priority 500 and `*' has priority 400, the term `2 * X + Y'
	% would parse as `(2 * X) + Y'.
	%
	% The lowest priority is 0.
:- type ops__priority == int.

%--------------------------------------------------%

	% An ops__specifier describes what structure terms
	% constructed with an operator are allowed to take.
	% `f' represents the operator and `x' and `y' represent arguments.
	% `x' represents an argument whose priority must be
	% strictly lower that that of the operator.
	% `y' represents an argument whose priority is
	% lower or equal to that of the operator.
	% For example, `yfx' indicates a left-associative infix operator,
	% while `xfy' indicates a right-associative infix operator.
:- type ops__specifier
	--->	fx ; fy ; xf ; yf ; xfx ; yfx ; xfy ; fxx ; fxy ; fyx.

:- type ops__assoc
	--->	x ; y.

:- type ops__class
	--->	infix(ops__assoc, ops__assoc)
	;	prefix(ops__assoc)
	;	binary_prefix(ops__assoc, ops__assoc)
	;	postfix(ops__assoc).

	% convert an ops__specifer (e.g. `xfy') to an ops__class
	% (e.g. `infix(x, y)').
:- pred ops__op_specifier_to_class(ops__specifier::in, ops__class::out) is det.

%--------------------------------------------------%


Node:parser, Next:, Previous:ops, Up:Top

38 parser


%--------------------------------------------------%
% Copyright (C) 1995-2001, 2003-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: parser.m.
% main author: fjh.
% stability: high.
%
% This file exports the predicate parser__read_term, which reads
% a term from the current input stream.
% The parser__read_term_from_string predicates are the same as the
% read_term predicates, except that the term is read from
% a string rather than from the current input stream.
% The parser__parse_token_list predicate is similar,
% but it takes a list of tokens rather than a string.
%
% The parser and lexer are intended to exactly follow ISO Prolog
% syntax, but there are some departures from that for three reasons:
%
%	(1) I wrote some of the code at home when the ISO Prolog draft
%	    was at uni - so in some places I just guessed.
%	(2) In some places the lexer reports an error when it shouldn't.
%	(3) There are a couple of hacks to make it compatible with NU-Prolog
%	    syntax.
%
% The parser is a relatively straight-forward top-down recursive descent
% parser, made somewhat complicated by the need to handle operator
% precedences.  It uses `lexer__get_token_list' to read a list of tokens.
% It uses the routines in module `ops' to look up operator precedences.
%
%--------------------------------------------------%

:- module parser.
:- interface.
:- import_module io, ops, term_io, lexer.

%--------------------------------------------------%

	%
	% parser__read_term/{3,4}:
	%	Reads in (and parses) terms from the current input stream.

	% parser__read_term(Result):
	%	Reads a Mercury term from the current input stream.
:- pred parser__read_term(read_term(T)::out, io::di, io::uo) is det.

	% parser__read_term_with_op_table(Result):
	%	Reads a term from the current input stream, using the
	%	given op_table to interpret the operators.
:- pred parser__read_term_with_op_table(Ops::in, read_term(T)::out,
	io::di, io::uo) is det <= op_table(Ops).

	% parser__read_term(FileName, Result):
	%	Reads a term from the current input stream.
	%	The string is the filename to use for the current input stream;
	%	this is used in constructing the term__contexts in the read
	%	term. This interface is used to support the `:- pragma
	%	source_file' directive.
:- pred parser__read_term(string::in, read_term(T)::out, io::di, io::uo)
	is det.

	% parser__read_term_with_op_table(Ops, FileName, Result):
	%	As above but using the given op_table.
:- pred parser__read_term_with_op_table(Ops::in, string::in, read_term(T)::out,
	io::di, io::uo) is det <= op_table(Ops).

%--------------------------------------------------%
	%
	% parser__read_term_from_string/{4,6}:
	%	Parses terms from a string.

	% The read_term_from_string predicates are the same as the
	% read_term predicates, except that the term is read from
	% a string rather than from the current input stream.
	% The returned value `EndPos' is the position one character
	% past the end of the term read.
	% The arguments `MaxOffset' and `StartPos' in the six-argument version
	% specify the length of the string and the position within the
	% string at which to start parsing.

	% parser__read_term_from_string(FileName, String, EndPos, Term).
:- pred parser__read_term_from_string(string::in, string::in, posn::out,
	read_term(T)::out) is det.

	% parser__read_term_from_string_with_op_table(Ops, FileName,
	%	String, EndPos, Term).
:- pred parser__read_term_from_string_with_op_table(Ops::in, string::in,
	string::in, posn::out, read_term(T)::out) is det <= op_table(Ops).

	% parser__read_term_from_string(FileName, String, MaxOffset, StartPos,
	%	EndPos, Term).
:- pred parser__read_term_from_string(string::in, string::in, int::in,
	posn::in, posn::out, read_term(T)::out) is det.

	% parser__read_term_from_string_with_op_table(Ops, FileName, String,
	%	MaxOffset, StartPos, EndPos, Term).
:- pred parser__read_term_from_string_with_op_table(Ops::in, string::in,
	string::in, int::in, posn::in, posn::out, read_term(T)::out) is det
	<= op_table(Ops).

%--------------------------------------------------%
	%
	% parser__parse_tokens/{3,4}:
	%	Parses a list of tokens.

	% parser__parse_tokens(FileName, TokenList, Result):
:- pred parser__parse_tokens(string::in, token_list::in, read_term(T)::out)
	is det.

	% parser__parse_tokens(FileName, TokenList, Result):
:- pred parser__parse_tokens_with_op_table(Ops::in, string::in,
	token_list::in, read_term(T)::out) is det <= op_table(Ops).

%--------------------------------------------------%


Node:pprint, Next:, Previous:parser, Up:Top

39 pprint


%--------------------------------------------------%
% vim:ts=4 sw=4 expandtab tw=0 wm=0
%--------------------------------------------------%
% Copyright (C) 2000-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: pprint.m
% Main author: rafe
% Stability: medium
%
%
% ABOUT
% -----
%
% This started off as pretty much a direct transliteration of Philip
% Wadler's Haskell pretty printer described in "A Prettier Printer",
% available at
% http://cm.bell-labs.com/cm/cs/who/wadler/topics/recent.html
%
% Several changes have been made to the algorithm to preserve linear
% running time under a strict language and to ensure scalability to
% extremely large terms without thrashing the VM system.
%
% Wadler's approach has three main advantages:
% 1. the layout algebra is small and quite intuitive (more
%    so than Hughes');
% 2. the pretty printer is optimal in the sense that it will
%    never generate output that over-runs the specified width
%    unless that is unavoidable; and
% 3. the pretty printer is bounded in that it never needs to
%    look more than k characters ahead to make a formatting
%    decision.
%
% I have made the following changes:
%
% (a) rather than having group/1 as a non-primitive function (for
% allowing line-breaks to be converted into spaces at the pretty
% printer's discretion) over docs, I have extended the doc type to
% include a `GROUP' constructor and made the appropriate algorithmic
% changes.  Because `UNION' only arises as a consequence of processing
% a 'GROUP' it turns out to be simpler to do away with `UNION'
% altogether and convert clauses that process `UNION' terms to
% processing `GROUP's.
%
% (b) Flattened `line' breaks become empty strings rather than spaces.
%
% (c) The third change is the introduction of the `LABEL' constructor,
% which acts much like `NEST', except that indentation is defined
% using a string rather than a number of spaces.  This is useful for,
% e.g., multi-line compiler errors and warnings that should be
% prefixed with the offending source file and line number.
%
% (d) The formatting decision procedure has been altered to preserve
% linear runtime behaviour in a strict language.
%
% (e) Naively marking up a term as a doc has the drawback that the
% resulting doc is significantly larger than the original term.
% Worse, any sharing structure in the original term leads to
% duplicated sub-docs, which can cause an exponential blow-up in the
% size of the doc w.r.t. the source term.  To get around this problem
% I have introduced the 'DOC' constructor which causes on-demand
% conversion of arguments.
%
% [This is not true laziness in the sense that the 'DOC', once
% evaluated, will be overwritten with its value.  This approach would
% lead to garbage retention and not solve the page thrashing behaviour
% otherwise experienced when converting extremely large terms.
% Instead, each 'DOC' is reevaluated each time it is examined.  This
% trades off computation time for space.]
%
% I have added several obvious general purpose formatting functions.
%
%
% USAGE
% -----
%
% There are two stages in pretty printing an object of some
% type T:
% 1. convert the object to a pprint__doc using the
%    constructor functions described below or by simply
%    calling pprint__to_doc/[1,2];
% 2. call pprint__write/[4,5] or pprint__to_string/2
%    passing the display width and the doc.
%
%
% EXAMPLES
% --------
%
% The doc/1 type class has types string, char, int, float and doc as
% instances.  Hence these types can all be converted to docs by
% applying doc/1.  This happens automatically to the arguments of ++/2.
% Users may find it convenient to add other types as instances of the
% doc/1 type class.
%
% Below are some docs followed by the ways they might be
% displayed by the pretty printer given various line widths.
%
% 1. "Hello " ++ line ++ "world"
%
%   Hello
%   world
%
% 2. group("Hello " ++ line ++ "world")
%
%   Hello world
%
%   Hello
%   world
%
% 3. group("Hello " ++ nest(3, line ++ "world"))
%
%   Hello world
%
%   Hello
%      world
%
% 4. group("Goodbye " ++ nest(3, line ++ "cruel " ++ line ++ "world")
%
%   Goodbye cruel world
%
%   Goodbye
%      cruel
%      world
%
% 5. group("Goodbye " ++ nest(3, line ++ group("cruel " ++ line ++ "world")))
%
%   Goodbye cruel world
%
%   Goodbye
%      cruel world
%
%   Goodbye
%      cruel
%      world
%
% 6. label("Look! ", line ++
%                    group("Goodbye " ++
%                          nest(3, line ++ group("cruel " ++ line ++ "world"))))
%
%   Look! Goodbye cruel world
%
%   Look! Goodbye
%   Look!    cruel world
%
%   Look! Goodbye
%   Look!    cruel
%   Look!    world
%
%--------------------------------------------------%

:- module pprint.

:- interface.

:- import_module std_util, int, string, char, float, list, io.

    % Clients must translate data structures into docs for
    % the pretty printer to display.
    %
:- type doc.

    % This typeclass can be used to simplify the construction of docs.
    %
:- typeclass doc(T) where [

        % Convert a T to a doc, placing a limit on how much of the
        % term will be fully converted as follows:
        %
        % doc(_, f         ) = f
        % doc(N, f(A, B, C)) = f/3 if N =< 0
        % doc(N, f(A, B, C)) = some representation of the term whereby
        %   A is converted as doc(N - 1, A),
        %   B is converted as doc(N - 2, B), and
        %   C is converted as doc(N - 3, C)
        %   - if there are more than N arguments, the N+1th and subsequent
        %     arguments should be replaced with a single ellipsis.
        %
    func doc(int, T) = doc
].

:- instance doc(doc).
:- instance doc(string).
:- instance doc(int).
:- instance doc(float).
:- instance doc(char).

    % Fully convert an instance of doc/1.
    %
:- func doc(T) = doc <= (doc(T)).

    % An alternative to the <>/2 concatenation operator that works
    % on members of the doc/1 typeclass.
    %
:- func T1 ++ T2 = doc <= (doc(T1), doc(T2)).

    % The empty document corresponding to the null string.
    %
:- func nil                 = doc.

    % The document consisting of a single string.
    %
    % NOTE: since string is now an instance of the doc/1
    % type class, it is simpler to just apply the doc/1
    % method.
    %
:- func text(string)        = doc.

    % The composition of two docs with no intervening space.
    %
    % NOTE: with the addition of the doc/1 type class, it is
    % simpler to construct compound docs using ++/2.
    %
:- func doc `<>` doc        = doc.

    % The new-line document.  In a group doc (see below) the
    % pretty printer may choose to instead `flatten' all
    % line docs into nil docs in order to fit a doc on a
    % single line.
    %
:- func line                = doc.

    % Any `line' docs in the body that are not flattened out
    % by the pretty printer are followed by the given number
    % of spaces (nested `nest's add up).
    %
:- func nest(int, T)        = doc <= (doc(T)).

    % Identical to a nest doc except that indentation is
    % extended with a string label rather than some number
    % of spaces.
    %
:- func label(string, T)    = doc <= (doc(T)).

    % A group doc gives the pretty printer a choice: if
    % the doc can be printed without line wrapping then
    % it does so (all line, label, nest and group
    % directives within the group are ignored); otherwise
    % the pretty printer treats the group body literally,
    % although nested group docs remain as choice points.
    %
:- func group(T)            = doc <= (doc(T)).

    % This function can be used to convert strings, chars,
    % ints and floats to their text doc equivalents.
    %
    % NOTE: since these types are now instances of the doc/1
    % type class, it is simpler to just apply the doc/1
    % method to these types.
    %
:- func poly(string__poly_type) = doc.

    % Shorthand for doc ++ line ++ doc.
    %
:- func doc `</>` doc       = doc.

    % Various bracketing functions.
    %
    %   bracketed(L, R, Doc) = L ++ Doc ++ R
    %       parentheses(Doc) = bracketed("(", ")", Doc)
    %          brackets(Doc) = bracketed("[", "]", Doc)
    %            braces(Doc) = bracketed("{", "}", Doc)
    %
:- func bracketed(T1, T2, T3)  = doc <= (doc(T1), doc(T2), doc(T3)).
:- func parentheses(T)         = doc <= (doc(T)).
:- func brackets(T)            = doc <= (doc(T)).
:- func braces(T)              = doc <= (doc(T)).

    % packed(Sep, [X1, X2, .., Xn]) = G1 `<>` G2 `<>` .. `<>` Gn where
    % Gi = group(line `<>` Xi `<>` Sep), except for Gn where
    % Gn = group(line `<>` Xn).
    %
    % For the singleton list case, packed(Sep, [X]) = group(line `<>` X).
    %
    % The resulting doc tries to pack as many items on a line as
    % possible.
    %
:- func packed(T1, list(T2)) = doc <= (doc(T1), doc(T2)).

    % A variant of the above whereby only the first N elements of
    % the list are formatted and the rest are replaced by a single
    % ellipsis.
    %
:- func packed(int, T1, list(T2)) = doc <= (doc(T1), doc(T2)).

    % packed_cs(Xs) = packed(comma_space, Xs).
    %
    % For example, to pretty print a Mercury list of docs
    % one might use
    %
    %   brackets(nest(2, packed_cs(Xs)))
    %
:- func packed_cs(list(T)) = doc <= (doc(T)).

    % A variant of the above whereby only the first N elements of
    % the list are formatted and the rest are replaced by a single
    % ellipsis.
    %
:- func packed_cs(int, list(T)) = doc <= (doc(T)).

    % This is like a depth-limited version of packed_cs/1 that first
    % calls to_doc/2 on each member of the argument list.
    %
:- func packed_cs_to_depth(int, list(T)) = doc.

    % This is like a version of packed_cs_to_depth/1 that first
    % calls univ_value/1 for each member of the argument list.
    %
:- func packed_cs_univ_args(int, list(univ)) = doc.

    % separated(PP, Sep, [X1,...,Xn]) =
    %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
    %
:- func separated(func(T1) = doc, T2, list(T1)) = doc <= (doc(T2)).

    % Handy punctuation docs and versions with following
    % spaces and/or line breaks.
    %
:- func comma               = doc.
:- func semic               = doc.      % Semicolon.
:- func colon               = doc.
:- func space               = doc.
:- func comma_space         = doc.
:- func semic_space         = doc.
:- func colon_space         = doc.
:- func comma_line          = doc.
:- func semic_line          = doc.
:- func colon_line          = doc.
:- func space_line          = doc.
:- func comma_space_line    = doc.
:- func semic_space_line    = doc.
:- func colon_space_line    = doc.
:- func ellipsis            = doc.      % "...".

    % Performs word wrapping at the end of line, taking
    % whitespace sequences as delimiters separating words.
    %
:- func word_wrapped(string) = doc.

    % Convert arbitrary terms to docs.  This requires
    % std_util__functor/3 to work on all components of the
    % object being converted.  The second version places a
    % maximum depth on terms which are otherwise truncated
    % in the manner described in the documentation for the
    % doc/2 method of the doc/1 type class.
    %
    % This may throw an exception or cause a runtime abort
    % if the term in question has user-defined equality.
    %
:- func to_doc(T)           = doc.
:- func to_doc(int, T)      = doc.

    % Convert docs to pretty printed strings.  The int
    % argument specifies a line width in characters.
    %
:- func to_string(int, doc) = string.

    % Write docs out in pretty printed format.  The int
    % argument specifies a page width in characters.
    %
:- pred write(int::in, T::in, io::di, io::uo) is det <= doc(T).

:- pred write(io__output_stream::in, int::in, T::in, io::di, io::uo) is det
    <= doc(T).

%--------------------------------------------------%
%--------------------------------------------------%


Node:pqueue, Next:, Previous:pprint, Up:Top

40 pqueue


%--------------------------------------------------%
% Copyright (C) 1994-1995, 1997, 1999, 2003-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 pqueue.m - implements a priority queue ADT.
% main author: conway.
% stability: high.
%
% A pqueue is a priority queue.  A priority queue holds a collection
% of key-value pairs; the interface provides operations to create
% an empty priority queue, to insert a key-value pair into a priority
% queue, and to remove the element with the lowest key.
%
% Insertion/removal is not guaranteed to be "stable"; that is,
% if you insert two values with the same key, the order in which
% they will be removed is unspecified.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module pqueue.

:- interface.

:- import_module assoc_list.

:- type pqueue(_K, _V).

	% Create an empty priority queue
:- pred pqueue__init(pqueue(_K, _V)::out) is det.
:- func pqueue__init = pqueue(_K, _V).

	% Insert a value V with key K into a priority queue
	% and return the new priority queue.
:- pred pqueue__insert(pqueue(K, V)::in, K::in, V::in, pqueue(K, V)::out)
	is det.
:- func pqueue__insert(pqueue(K, V), K, V) = pqueue(K, V).

	% Remove the smallest item from the priority queue.
:- pred pqueue__remove(pqueue(K, V)::in, K::out, V::out, pqueue(K, V)::out)
	is semidet.

	% Extract all the items from a priority queue by
	% repeated removal, and place them in an association
	% list.
:- pred pqueue__to_assoc_list(pqueue(K, V)::in, assoc_list(K, V)::out) is det.
:- func pqueue__to_assoc_list(pqueue(K, V)) = assoc_list(K, V).

	% Insert all the key-value pairs in an association list
	% into a priority queue.
:- pred pqueue__assoc_list_to_pqueue(assoc_list(K, V)::in, pqueue(K, V)::out)
	is det.
:- func pqueue__assoc_list_to_pqueue(assoc_list(K, V)) = pqueue(K, V).

%--------------------------------------------------%


Node:prolog, Next:, Previous:pqueue, Up:Top

41 prolog


%--------------------------------------------------%
% Copyright (C) 1997-2003 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: prolog.m.
% Main author: fjh.

% This file contains predicates that are intended to help people
% porting Prolog programs, or writing programs in the intersection
% of Mercury and Prolog.

%--------------------------------------------------%
:- module prolog.
:- interface.
:- import_module std_util, list.

% Prolog arithmetic operators.

:- pred T =:= T.			% In Mercury, just use =
:- mode in =:= in is semidet.

:- pred T =\= T.			% In Mercury, just use \=
:- mode in =\= in is semidet.

/*******
is/2 is currently defined in int.m, for historical reasons.

:- pred is(T, T) is det.		% In Mercury, just use =
:- mode is(uo, di) is det.
:- mode is(out, in) is det.
******/

% Prolog term comparison operators.

:- pred T == T.				% In Mercury, just use =
:- mode in == in is semidet.

:- pred T \== T.			% In Mercury, just use \=
:- mode in \== in is semidet.

% Prolog's so-called "univ" operator, `=..'.
% Note: this is not related to Mercury's "univ" type!
% In Mercury, use `deconstruct.deconstruct' instead.

:- pred T =.. univ_result.
:- mode in =.. out is det.
	%
	% Note that the Mercury =.. is a bit different to the Prolog
	% one.  We could make it slightly more similar by overloading '.'/2,
	% but that would cause ambiguities that might prevent type
	% inference in a lot of cases.
	%
% :- type univ_result ---> '.'(string, list(univ)).
:- type univ_result == pair(string, list(univ)).

	% arg/3.  In Mercury, use argument/3 (defined in module std_util)
	% instead:
	%      arg(ArgNum, Term, Data) :- argument(Term, ArgNum - 1, Data).
	%
:- pred arg(int::in, T::in, univ::out) is semidet.

	% det_arg/3: like arg/3, but calls error/1 rather than failing
	% if the index is out of range.
	%
:- pred det_arg(int::in, T::in, univ::out) is det.
%--------------------------------------------------%


Node:queue, Next:, Previous:prolog, Up:Top

42 queue


%--------------------------------------------------%
% Copyright (C) 1994-1995, 1997-1999, 2003-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: queue.m.
% Main author: fjh.
% Stability: high.

% This file contains a `queue' ADT.
% A queue holds a sequence of values, and provides operations
% to insert values at the end of the queue (queue__put) and remove them from
% the front of the queue (queue__get).
%
% This implementation is in terms of a pair of lists.
% The put and get operations are amortized constant-time.

%--------------------------------------------------%

:- module queue.
:- interface.
:- import_module list.

:- type queue(T).

	% `queue__init(Queue)' is true iff `Queue' is an empty queue.

:- pred queue__init(queue(T)::out) is det.
:- func queue__init = queue(T).

	% 'queue_equal(Q1, Q2)' is true iff Q1 and Q2 contain the same
	% elements in the same order.

:- pred queue__equal(queue(T)::in, queue(T)::in) is semidet.

	% `queue__is_empty(Queue)' is true iff `Queue' is an empty queue.

:- pred queue__is_empty(queue(T)::in) is semidet.

	% `queue__is_full(Queue)' is intended to be true iff `Queue'
	% is a queue whose capacity is exhausted.  This
	% implementation allows arbitrary-sized queues, so queue__is_full
	% always fails.

:- pred queue__is_full(queue(T)::in) is semidet.

	% `queue__put(Queue0, Elem, Queue)' is true iff `Queue' is
	% the queue which results from appending `Elem' onto the end
	% of `Queue0'.

:- pred queue__put(queue(T)::in, T::in, queue(T)::out) is det.
:- func queue__put(queue(T), T) = queue(T).

	% `queue__put_list(Queue0, Elems, Queue)' is true iff `Queue'
	% is the queue which results from inserting the items in the
	% list `Elems' into `Queue0'.

:- pred queue__put_list(queue(T)::in, list(T)::in, queue(T)::out) is det.
:- func queue__put_list(queue(T), list(T)) = queue(T).

	% `queue__first(Queue, Elem)' is true iff `Queue' is a non-empty
	% queue whose first element is `Elem'.

:- pred queue__first(queue(T)::in, T::out) is semidet.

	% `queue__get(Queue0, Elem, Queue)' is true iff `Queue0' is
	% a non-empty queue whose first element is `Elem', and `Queue'
	% the queue which results from removing that element from
	% the front of `Queue0'.

:- pred queue__get(queue(T)::in, T::out, queue(T)::out) is semidet.

	% `queue__length(Queue, Length)' is true iff `Queue' is a queue
	% containing `Length' elements.

:- pred queue__length(queue(T)::in, int::out) is det.
:- func queue__length(queue(T)) = int.

	% `queue__list_to_queue(List, Queue)' is true iff `Queue' is a queue
	% containing the elements of List, with the first element of List at
	% the head of the queue.

:- pred queue__list_to_queue(list(T)::in, queue(T)::out) is det.
:- func queue__list_to_queue(list(T)) = queue(T).

	% `queue__delete_all(Queue0, Elem, Queue)' is true iff `Queue' is
	% the same queue as `Queue0' with all occurences of `Elem' removed
	% from it.
:- pred queue__delete_all(queue(T)::in, T::in, queue(T)::out) is det.
:- func queue__delete_all(queue(T), T) = queue(T).

%--------------------------------------------------%


Node:random, Next:, Previous:queue, Up:Top

43 random


%--------------------------------------------------%
% Copyright (C) 1994-1998,2001-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: random.m
% main author: conway
% stability: low
%
% Define a set of random number generator predicates. This implementation
% uses a threaded random-number supply.  The supply can be used in a
% non-unique way, which means that each thread returns the same list of
% random numbers.  However, this may not be desired so in the interests
% of safety it is also declared with (backtrackable) unique modes.
%
% The coefficients used in the implementation were taken from Numerical
% Recipes in C (Press et al), and are originally due to Knuth.  These
% coefficients are described as producing a "Quick and Dirty" random number
% generator, which generates the numbers very quickly but not necessarily
% with a high degree of quality.  As with all random number generators,
% the user is advised to consider carefully whether this generator meets
% their requirements in terms of "randomness".  For applications which have
% special needs (e.g. cryptographic key generation), a generator such as
% this is unlikely to be suitable.
%
% Note that random number generators of this type have several known
% pitfalls which the user may need to avoid:
%
%	1) The high bits tend to be more random than the low bits.  If
%	you wish to generate a random integer within a given range, you
%	should something like 'div' to reduce the random numbers to the
%	required range rather than something like 'mod' (or just use
%	random__random/5).
%
%	2) Similarly, you should not try to break a random number up into
%	components.  Instead, you should generate each number with a
%	separate call to this module.
%
%	3) There can be sequential correlation between successive calls,
%	so you shouldn't try to generate tuples of random numbers, for
%	example, by generating each component of the tuple in sequential
%	order.  If you do, it is likely that the resulting sequence will
%	not cover the full range of possible tuples.
%
%--------------------------------------------------%

:- module random.

:- interface.

:- import_module list.

	% The type `random__supply' represents a supply of random numbers.
:- type random__supply.

	% random__init(Seed, RS): creates a supply of random numbers RS
	% using the specified Seed.
:- pred random__init(int::in, random__supply::uo) is det.

	% random__random(Num, RS0, RS): extracts a number Num in the
	% range 0 .. RandMax from the random number supply RS0, and
	% binds RS to the new state of the random number supply.
:- pred random__random(int, random__supply, random__supply).
:- mode random__random(out, mdi, muo) is det.
:- mode random__random(out, in, out) is det.

	% random__random(Low, Range, Num, RS0, RS): extracts a number Num
	% in the range Low .. (Low + Range - 1) from the random number
	% supply RS0, and binds RS to the new state of the random number
	% supply.  For best results, the value of Range should be no greater
	% than about 100.
:- pred random__random(int, int, int, random__supply, random__supply).
:- mode random__random(in, in, out, mdi, muo) is det.
:- mode random__random(in, in, out, in, out) is det.

	% random__randmax(RandMax, RS0, RS): binds RandMax to the maximum
	% random number that can be returned from the random number
	% supply RS0, and returns RS = RS0.
:- pred random__randmax(int, random__supply, random__supply).
:- mode random__randmax(out, mdi, muo) is det.
:- mode random__randmax(out, in, out) is det.

	% random__randcount(RandCount, RS0, RS): binds RandCount to the
	% number of distinct random numbers that can be returned from the
	% random number supply RS0, and returns RS = RS0.  This will be one
	% more than the number returned by randmax/3.
:- pred random__randcount(int, random__supply, random__supply).
:- mode random__randcount(out, mdi, muo) is det.
:- mode random__randcount(out, in, out) is det.

	% random__permutation(List0, List, RS0, RS):
	% binds List to a random permutation of List0,
	% and binds RS to the new state of the random number supply.
:- pred random__permutation(list(T), list(T), random__supply, random__supply).
:- mode random__permutation(in, out, mdi, muo) is det.
:- mode random__permutation(in, out, in, out) is det.

%--------------------------------------------------%


Node:rational, Next:, Previous:random, Up:Top

44 rational


%--------------------------------------------------%
% Copyright (C) 1997-1998, 2003-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: rational.m
% authors: aet Apr 1998. (with plagiarism from rat.m)
%
% Implements a rational number type and a set of basic operations on
% rational numbers.
%
%--------------------------------------------------%

:- module rational.

:- interface.

:- import_module integer.

:- type rational.

:- pred '<'(rational, rational).
:- mode '<'(in, in) is semidet.

:- pred '>'(rational, rational).
:- mode '>'(in, in) is semidet.

:- pred '=<'(rational, rational).
:- mode '=<'(in, in) is semidet.

:- pred '>='(rational, rational).
:- mode '>='(in, in) is semidet.

:- func rational__rational(int) = rational.

:- func rational__rational(int, int) = rational.

:- func rational__from_integer(integer) = rational.

:- func rational__from_integers(integer, integer) = rational.

	% New programs should use rational.from_integers/2.
:- pragma obsolete(rational_from_integers/2).
:- func rational__rational_from_integers(integer, integer) = rational.

% :- func float(rational) = float.

:- func '+'(rational) = rational.

:- func '-'(rational) = rational.

:- func rational + rational = rational.

:- func rational - rational = rational.

:- func rational * rational = rational.

:- func rational / rational = rational.

:- func rational__numer(rational) = integer.

:- func rational__denom(rational) = integer.

:- func rational__abs(rational) = rational.

:- func rational__reciprocal(rational) = rational.

:- func rational__one = rational.

:- func rational__zero = rational.

%--------------------------------------------------%
%--------------------------------------------------%


Node:rbtree, Next:, Previous:rational, Up:Top

45 rbtree


%--------------------------------------------------%
% Copyright (C) 1995-2000, 2003-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.
%--------------------------------------------------%
%
% Red-black tree module.
% Main author: petdr.
% Stability: medium.
%
% Contains an implementation of red black trees.
%
% *** Exit conditions of main predicates ***
% insert:
%	fails if key already in tree.
% update:
%	changes value of key already in tree.  fails if key doesn't exist.
% set:
%	inserts or updates. Never fails.
%
% insert_duplicate:
%	inserts duplicate keys into the tree, never fails.  Search doesn't
%	yet support looking for duplicates.
%
% delete:
%	deletes a node from the tree if it exists.
% remove:
%	fails if node to remove doesn't exist in the tree.
%
% lookup:
%	Aborts program if key looked up doesn't exist.
% search:
%	Fails if key looked up doesn't exist.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module rbtree.
:- interface.

:- import_module list, assoc_list.

:- type rbtree(Key, Value).

	% Initialise the data structure.
:- pred rbtree__init(rbtree(K, V)).
:- mode rbtree__init(uo) is det.

:- func rbtree__init = rbtree(K, V).

	% Check whether a tree is empty.
:- pred rbtree__is_empty(rbtree(K, V)).
:- mode rbtree__is_empty(in) is semidet.

	% Inserts a new key-value pair into the tree.  Fails if key
	% already in the tree.
:- pred rbtree__insert(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__insert(in, in, in, out) is semidet.

	% Updates the value associated with a key.  Fails if the key
	% doesn't exist.
:- pred rbtree__update(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__update(in, in, in, out) is semidet.

	% Sets a value irregardless of whether key exists or not.  Never
	% fails.
:- pred rbtree__set(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__set(di, di, di, uo) is det.
:- mode rbtree__set(in, in, in, out) is det.

:- func rbtree__set(rbtree(K, V), K, V) = rbtree(K, V).

	% Insert a duplicate key into the tree.  Never fails.
:- pred rbtree__insert_duplicate(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__insert_duplicate(in, in, in, out) is det.

:- func rbtree__insert_duplicate(rbtree(K, V), K, V) = rbtree(K, V).

:- pred rbtree__member(rbtree(K, V), K, V).
:- mode rbtree__member(in, out, out) is nondet.

	% Search for a key-value pair using the key.  Fails if key doesn't
	% exist.
:- pred rbtree__search(rbtree(K, V), K, V).
:- mode rbtree__search(in, in, out) is semidet.

	% Lookup a value associated with a key.  Program aborts if key
	% doesn't exist.
:- pred rbtree__lookup(rbtree(K, V), K, V).
:- mode rbtree__lookup(in, in, out) is det.

:- func rbtree__lookup(rbtree(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 rbtree__lower_bound_search(rbtree(K, V), K, K, V).
:- mode rbtree__lower_bound_search(in, in, out, 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 rbtree__lower_bound_lookup(rbtree(K, V), K, K, V).
:- mode rbtree__lower_bound_lookup(in, in, out, 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 rbtree__upper_bound_search(rbtree(K, V), K, K, V).
:- mode rbtree__upper_bound_search(in, in, out, 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 rbtree__upper_bound_lookup(rbtree(K, V), K, K, V).
:- mode rbtree__upper_bound_lookup(in, in, out, out) is det.

	% Delete the key value pair associated with a key.  Does nothing
	% if the key doesn't exist.
:- pred rbtree__delete(rbtree(K, V), K, rbtree(K, V)).
:- mode rbtree__delete(di, in, uo) is det.
:- mode rbtree__delete(in, in, out) is det.

:- func rbtree__delete(rbtree(K, V), K) = rbtree(K, V).

	% Remove the key value pair associated with a key.  Fails
	% if the key doesn't exist.
:- pred rbtree__remove(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__remove(di, in, uo, uo) is semidet.
:- mode rbtree__remove(in, in, out, out) is semidet.

	% Same as above, except this version does not return the value
	% corresponding to the key.  Its use is deprecated, but it is
	% kept for compatibility with older versions of this library.
:- pred rbtree__remove(rbtree(K, V), K, rbtree(K, V)).
:- mode rbtree__remove(in, in, out) is semidet.

	% Deletes the node with the minimum K from the tree, and returns
	% the key and value fields.
:- pred rbtree__remove_smallest(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__remove_smallest(di, uo, uo, uo) is semidet.
:- mode rbtree__remove_smallest(in, out, out, out) is semidet.

	% Deletes the node with the maximum K from the tree, and returns
	% the key and value fields.
:- pred rbtree__remove_largest(rbtree(K, V), K, V, rbtree(K, V)).
:- mode rbtree__remove_largest(di, uo, uo, uo) is semidet.
:- mode rbtree__remove_largest(in, out, out, out) is semidet.

	% Returns an in-order list of all the keys in the rbtree.
:- pred rbtree__keys(rbtree(K, V), list(K)).
:- mode rbtree__keys(in, out) is det.

:- func rbtree__keys(rbtree(K, V)) = list(K).

	% Returns a list of values such that the keys associated with the
	% values are in-order.
:- pred rbtree__values(rbtree(K, V), list(V)).
:- mode rbtree__values(in, out) is det.

:- func rbtree__values(rbtree(K, V)) = list(V).

	% Count the number of elements in the tree
:- pred rbtree__count(rbtree(K, V), int).
:- mode rbtree__count(in, out) is det.

:- func rbtree__count(rbtree(K, V)) = int.

:- pred rbtree__assoc_list_to_rbtree(assoc_list(K, V), rbtree(K, V)).
:- mode rbtree__assoc_list_to_rbtree(in, out) is det.

:- func rbtree__assoc_list_to_rbtree(assoc_list(K, V)) = rbtree(K, V).

:- pred rbtree__rbtree_to_assoc_list(rbtree(K, V), assoc_list(K, V)).
:- mode rbtree__rbtree_to_assoc_list(in, out) is det.

:- func rbtree__rbtree_to_assoc_list(rbtree(K, V)) = assoc_list(K, V).

:- pred rbtree__foldl(pred(K, V, T, T), rbtree(K, V), T, T).
:- mode rbtree__foldl(pred(in, in, in, out) is det, in, in, out) is det.
:- mode rbtree__foldl(pred(in, in, in, out) is semidet, in, in, out)
		is semidet.
:- mode rbtree__foldl(pred(in, in, di, uo) is det, in, di, uo) is det.

:- func rbtree__foldl(func(K, V, T) = T, rbtree(K, V), T) = T.

:- pred rbtree__map_values(pred(K, V, W), rbtree(K, V), rbtree(K, W)).
:- mode rbtree__map_values(pred(in, in, out) is det, in, out) is det.
:- mode rbtree__map_values(pred(in, in, out) is semidet, in, out) is semidet.

:- func rbtree__map_values(func(K, V) = W, rbtree(K, V)) = rbtree(K, W).

%--------------------------------------------------%


Node:relation, Next:, Previous:rbtree, Up:Top

46 relation


%--------------------------------------------------%
% Copyright (C) 1995-1999,2002-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: relation.m.
% main author: bromage, petdr.
% stability: low.
%
% This module defines a data type for binary relations over reflexive
% domains.
%
% In fact, this is exactly equivalent to a graph/1 type.
%--------------------------------------------------%
%--------------------------------------------------%

:- module relation.

:- interface.
:- import_module enum, list, set, assoc_list, sparse_bitset.

:- type relation(T).

:- type relation_key.

:- instance enum(relation_key).

:- type relation_key_set == sparse_bitset(relation_key).

	% relation__init creates a new relation.
:- pred relation__init(relation(T)::out) is det.
:- func relation__init = relation(T).

	% relation__add_element adds an element to the domain of a
	% relation.  Return the old relation_key if one already
	% exists.
:- pred relation__add_element(relation(T)::in, T::in, relation_key::out,
	relation(T)::out) is det.

	% relation__search_element returns the relation_key associated
        % with a domain element.  Fail if the relation_key is not valid.
:- pred relation__search_element(relation(T)::in, T::in, relation_key::out)
	is semidet.

	% relation__lookup_element returns the relation_key associated
        % with a domain element.  Abort if the relation_key is not valid.
:- pred relation__lookup_element(relation(T)::in, T::in, relation_key::out)
	is det.
:- func relation__lookup_element(relation(T), T) = relation_key.

	% relation__search_key returns the domain element associated
	% with a relation_key.  Fail if the relation_key is not valid.
:- pred relation__search_key(relation(T)::in, relation_key::in, T::out)
	is semidet.

	% relation__lookup_key returns the domain element associated
	% with a relation_key.  Abort if the relation_key is not valid.
:- pred relation__lookup_key(relation(T)::in, relation_key::in, T::out) is det.
:- func relation__lookup_key(relation(T), relation_key) = T.

	% relation__add adds an element to the relation.
:- pred relation__add(relation(T)::in, relation_key::in, relation_key::in,
	relation(T)::out) is det.
:- func relation__add(relation(T), relation_key, relation_key) = relation(T).

	% relation__add_values adds an pair of values to the relation's
	% domain and adds an element to the relation.
	%
	% relation__add_values(R0, X, Y, R) :-
	%	 relation__add_element(R0, X, XKey, R1),
	%	 relation__add_element(R1, Y, YKey, R2),
	%	 relation__add(R1, XKey, YKey, R).
	%
:- pred relation__add_values(relation(T)::in, T::in, T::in, relation(T)::out)
	is det.
:- func relation__add_values(relation(T), T, T) = relation(T).

	% relation__add_assoc_list adds a list of elements to a
	% relation.
:- pred relation__add_assoc_list(relation(T)::in,
	assoc_list(relation_key, relation_key)::in, relation(T)::out) is det.

:- func relation__add_assoc_list(relation(T),
	assoc_list(relation_key, relation_key)) = relation(T).

	% relation__remove removes an element from the relation.
:- pred relation__remove(relation(T)::in, relation_key::in, relation_key::in,
	relation(T)::out) is det.

:- func relation__remove(relation(T), relation_key, relation_key)
	= relation(T).

	% relation__remove_assoc_list removes a list of elements
	% from a relation.
:- pred relation__remove_assoc_list(relation(T)::in,
	assoc_list(relation_key, relation_key)::in, relation(T)::out) is det.

:- func relation__remove_assoc_list(relation(T),
	assoc_list(relation_key, relation_key)) = relation(T).

	% relation__lookup checks to see if an element is
	% in the relation.
:- pred relation__lookup(relation(T), relation_key, relation_key).
:- mode relation__lookup(in, in, out) is nondet.
:- mode relation__lookup(in, in, in) is semidet.

	% relation__reverse_lookup checks to see if an element is
	% in the relation.
:- pred relation__reverse_lookup(relation(T), relation_key, relation_key).
:- mode relation__reverse_lookup(in, out, in) is nondet.
:- mode relation__reverse_lookup(in, in, in) is semidet.

	% relation__lookup_from returns the set of elements
	% y such that xRy, given an x.
:- pred relation__lookup_from(relation(T)::in, relation_key::in,
	set(relation_key)::out) is det.
:- func relation__lookup_from(relation(T), relation_key) = set(relation_key).

:- pred relation__lookup_key_set_from(relation(T)::in,
	relation_key::in, relation_key_set::out) is det.

:- func relation__lookup_key_set_from(relation(T), relation_key)
	= relation_key_set.

	% relation__lookup_to returns the set of elements
	% x such that xRy, given some y.
:- pred relation__lookup_to(relation(T)::in, relation_key::in,
	set(relation_key)::out) is det.

:- func relation__lookup_to(relation(T), relation_key) = set(relation_key).

:- pred relation__lookup_key_set_to(relation(T)::in,
	relation_key::in, relation_key_set::out) is det.
:- func relation__lookup_key_set_to(relation(T), relation_key)
	= relation_key_set.

	% relation__to_assoc_list turns a relation into a list of
	% pairs of elements.
:- pred relation__to_assoc_list(relation(T)::in, assoc_list(T, T)::out) is det.
:- func relation__to_assoc_list(relation(T)) = assoc_list(T, T).

	% relation__to_key_assoc_list turns a relation into a list of
	% pairs of relation keys.
:- pred relation__to_key_assoc_list(relation(T)::in,
	assoc_list(relation_key, relation_key)::out) is det.
:- func relation__to_key_assoc_list(relation(T))
	= assoc_list(relation_key, relation_key).

	% relation__from_assoc_list turns a list of pairs of
	% elements into a relation.
:- pred relation__from_assoc_list(assoc_list(T, T)::in, relation(T)::out)
	is det.
:- func relation__from_assoc_list(assoc_list(T, T)) = relation(T).

	% relation__domain finds the set of all elements in the
	% domain of a relation.
:- pred relation__domain(relation(T)::in, set(T)::out) is det.
:- func relation__domain(relation(T)) = set(T).

	% relation__inverse(R, R') is true iff for all x, y
	% in the domain of R, xRy if yR'x.
:- pred relation__inverse(relation(T)::in, relation(T)::out) is det.
:- func relation__inverse(relation(T)) = relation(T).

	% relation__compose(R1, R2, R) is true if R is the
	% composition of the relations R1 and R2.
:- pred relation__compose(relation(T)::in, relation(T)::in, relation(T)::out)
	is det.
:- func relation__compose(relation(T), relation(T)) = relation(T).

	% relation__dfs(Rel, X, Dfs) is true if Dfs is a
	% depth-first sorting of Rel starting at X.  The
	% set of elements in the list Dfs is exactly equal
	% to the set of elements y such that xR*y, where
	% R* is the reflexive transitive closure of R.
:- pred relation__dfs(relation(T)::in, relation_key::in,
	list(relation_key)::out) is det.
:- func relation__dfs(relation(T), relation_key) = list(relation_key).

	% relation__dfsrev(Rel, X, DfsRev) is true if DfsRev is a
	% reverse depth-first sorting of Rel starting at X.  The
	% set of elements in the list Dfs is exactly equal
	% to the set of elements y such that xR*y, where
	% R* is the reflexive transitive closure of R.
:- pred relation__dfsrev(relation(T)::in, relation_key::in,
	list(relation_key)::out) is det.
:- func relation__dfsrev(relation(T), relation_key) = list(relation_key).

	% relation__dfs(Rel, Dfs) is true if Dfs is a depth-
	% first sorting of Rel, i.e. a list of the nodes in Rel
	% such that it contains all elements in the relation and all
	% the children of a node are placed in the list before
	% the parent.
:- pred relation__dfs(relation(T)::in, list(relation_key)::out) is det.
:- func relation__dfs(relation(T)) = list(relation_key).

	% relation__dfsrev(Rel, DfsRev) is true if DfsRev is a reverse
	% depth-first sorting of Rel.  ie DfsRev is the reverse of Dfs
	% from relation__dfs/2.
:- pred relation__dfsrev(relation(T)::in, list(relation_key)::out) is det.
:- func relation__dfsrev(relation(T)) = list(relation_key).

	% relation__dfs(Rel, X, Visit0, Visit, Dfs) is true
	% if Dfs is a depth-first sorting of Rel starting at
	% X providing we have already visited Visit0 nodes,
	% i.e.  a list of nodes such that all the unvisited
	% children of a node are placed in the list before the
	% parent.  Visit0 allows us to initialise a set of
	% previously visited nodes.  Visit is Dfs + Visit0.
:- pred relation__dfs(relation(T)::in, relation_key::in, relation_key_set::in,
	relation_key_set::out, list(relation_key)::out) is det.

	% relation__dfsrev(Rel, X, Visit0, Visit, DfsRev) is true if
	% DfsRev is a reverse depth-first sorting of Rel starting at X
	% providing we have already visited Visit0 nodes,
	% ie the reverse of Dfs from relation__dfs/5.
	% Visit is Visit0 + DfsRev.
:- pred relation__dfsrev(relation(T)::in, relation_key::in,
	relation_key_set::in, relation_key_set::out, list(relation_key)::out)
	is det.

	% relation__is_dag(R) is true iff R is a directed acyclic graph.
:- pred relation__is_dag(relation(T)::in) is semidet.

	% relation__components(R, Comp) is true if Comp
	% is the set of the connected components of R.
:- pred relation__components(relation(T)::in, set(set(relation_key))::out)
	is det.
:- func relation__components(relation(T)) = set(set(relation_key)).

	% relation__cliques(R, Cliques) is true if
	% Cliques is the set of the strongly connected
	% components (cliques) of R.
:- pred relation__cliques(relation(T)::in, set(set(relation_key))::out) is det.
:- func relation__cliques(relation(T)) = set(set(relation_key)).

	% relation__reduced(R, Red) is true if Red is
	% the reduced relation (relation of cliques)
	% obtained from R.
:- pred relation__reduced(relation(T)::in, relation(set(T))::out) is det.
:- func relation__reduced(relation(T)) = relation(set(T)).

	% relation__tsort(R, TS) is true if TS is a
	% topological sorting of R.  It fails if R
	% is cyclic.
:- pred relation__tsort(relation(T)::in, list(T)::out) is semidet.

	% relation__atsort(R, ATS) is true if ATS is
	% a topological sorting of the cliques in R.
:- pred relation__atsort(relation(T)::in, list(set(T))::out) is det.
:- func relation__atsort(relation(T)) = list(set(T)).

	% relation__sc(R, SC) is true if SC is the
	% symmetric closure of R.  In graph terms,
	% symmetric closure is the same as turning
	% a directed graph into an undirected graph.
:- pred relation__sc(relation(T)::in, relation(T)::out) is det.
:- func relation__sc(relation(T)) = relation(T).

	% relation__tc(R, TC) is true if TC is the
	% transitive closure of R.
:- pred relation__tc(relation(T)::in, relation(T)::out) is det.
:- func relation__tc(relation(T)) = relation(T).

	% relation__rtc(R, RTC) is true if RTC is the
	% reflexive transitive closure of R.
:- pred relation__rtc(relation(T)::in, relation(T)::out) is det.
:- func relation__rtc(relation(T)) = relation(T).

	% relation__traverse(R, ProcessNode, ProcessEdge) will
	% traverse a relation calling ProcessNode for each node in the
	% relation and ProcessEdge for each edge in the relation.
	% Each node is processed followed by all the edges originating
	% at that node, until all nodes have been processed.
:- pred relation__traverse(relation(K), pred(K, T, T), pred(K, K, T, T), T, T).
:- mode relation__traverse(in, pred(in, di, uo) is det,
	pred(in, in, di, uo) is det, di, uo) is det.
:- mode relation__traverse(in, pred(in, in, out) is det,
	pred(in, in, in, out) is det, in, out) is det.

%--------------------------------------------------%


Node:require, Next:, Previous:relation, Up:Top

47 require


%--------------------------------------------------%
% Copyright (C) 1993-1999, 2003 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.
%--------------------------------------------------%

:- module require.

% Main author: fjh.
% Stability: medium to high.

% This module provides features similar to <assert.h> in C.

%--------------------------------------------------%
:- interface.

:- type software_error ---> software_error(string).

:- pred error(string).
:- mode error(in) is erroneous.

%	error(Message).
%		Throw a `software_error(Message)' exception.
%		This will normally cause execution to abort with an error
%		message.

:- func func_error(string) = _.
:- mode func_error(in) = out is erroneous.

%	func_error(Message)
%		An expression that results in a `software_error(Message)'
%		exception being thrown.

:- pred	require(pred, string).
:- mode	require((pred) is semidet, in) is det.

%	require(Goal, Message).
%		Call goal, and call error(Message) if Goal fails.
%		This is not as useful as you might imagine, since it requires
%		that the goal not produce any output variables.  In
%		most circumstances you should use an explicit if-then-else
%		with a call to error/1 in the "else".

:- pred report_lookup_error(string, K, V).
:- mode report_lookup_error(in, in, unused) is erroneous.

%	report_lookup_error(Message, Key, Value)
%		Call error/1 with an error message that is appropriate for
%		the failure of a lookup operation involving the specified
%		Key and Value.  The error message will include Message
%		and information about Key and Value.

%--------------------------------------------------%


Node:set, Next:, Previous:require, Up:Top

48 set


%--------------------------------------------------%
% Copyright (C) 1994-1997, 1999-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: set.m.
% Main authors: conway, fjh, benyi.
% Stability: high.

% This module provides a set ADT.
% The implementation represents sets using ordered lists.
% This file just calls the equivalent predicates in set_ordlist.

%--------------------------------------------------%

:- module set.
:- interface.
:- import_module bool, list.

:- type set(T).

	% `set__list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'.

:- pred set__list_to_set(list(T)::in, set(T)::out) is det.
:- func set__list_to_set(list(T)) = set(T).

	% `set__sorted_list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'.  `List' must be sorted
	% and must not contain any duplicates.

:- pred set__sorted_list_to_set(list(T)::in, set(T)::out) is det.
:- func set__sorted_list_to_set(list(T)) = set(T).

	% `set__to_sorted_list(Set, List)' is true iff `List' is the list
	% of all the members of `Set', in sorted order without any
	% duplicates.

:- pred set__to_sorted_list(set(T)::in, list(T)::out) is det.
:- func set__to_sorted_list(set(T)) = list(T).

	% `set__init(Set)' is true iff `Set' is an empty set.

:- pred set__init(set(T)::uo) is det.
:- func set__init = set(T).

	% `set__singleton_set(Set, Elem)' is true iff `Set' is the set
	% containing just the single element `Elem'.

:- pred set__singleton_set(set(T), T).
:- mode set__singleton_set(in, out) is semidet.
:- mode set__singleton_set(out, in) is det.

:- func set__make_singleton_set(T) = set(T).

	% `set__equal(SetA, SetB)' is true iff
	% `SetA' and `SetB' contain the same elements.

:- pred set__equal(set(T)::in, set(T)::in) is semidet.

:- pred set__empty(set(T)::in) is semidet.

:- pred set__non_empty(set(T)::in) is semidet.

	% `set__subset(SetA, SetB)' is true iff `SetA' is a subset of `SetB'.

:- pred set__subset(set(T)::in, set(T)::in) is semidet.

	% `set__superset(SetA, SetB)' is true iff `SetA' is a
	% superset of `SetB'.

:- pred set__superset(set(T)::in, set(T)::in) is semidet.

	% `set__member(X, Set)' is true iff `X' is a member of `Set'.

:- pred set__member(T, set(T)).
:- mode set__member(in, in) is semidet.
:- mode set__member(out, in) is nondet.

	% `set_is_member(X, Set, Result)' returns
	% `Result = yes' iff `X' is a member of `Set'.

:- pred set__is_member(T::in, set(T)::in, bool::out) is det.

	% `set__contains(Set, X)' is true iff `X' is a member of `Set'.

:- pred set__contains(set(T)::in, T::in) is semidet.

	% `set__insert(Set0, X, Set)' is true iff `Set' is the union of
	% `Set0' and the set containing only `X'.

:- pred set__insert(set(T), T, set(T)).
:- mode set__insert(di, di, uo) is det.
:- mode set__insert(in, in, out) is det.

	% XXX rwab1: I think we should reverse the args. here for
	% higher order programming.
:- func set__insert(set(T), T) = set(T).

	% `set__insert_list(Set0, Xs, Set)' is true iff `Set' is the union of
	% `Set0' and the set containing only the members of `Xs'.

:- pred set__insert_list(set(T)::in, list(T)::in, set(T)::out) is det.

	% XXX rwab1: I think we should reverse the args. here for
	% higher order programming.
:- func set__insert_list(set(T), list(T)) = set(T).

	% `set__delete(Set0, X, Set)' is true iff `Set' is the relative
	% complement of `Set0' and the set containing only `X', i.e.
	% if `Set' is the set which contains all the elements of `Set0'
	% except `X'.

:- pred set__delete(set(T), T, set(T)).
% :- mode set__delete(di, in, uo) is det.
:- mode set__delete(in, in, out) is det.

	% XXX rwab1: I think we should reverse the args. here for
	% higher order programming.
:- func set__delete(set(T), T) = set(T).

	% `set__delete_list(Set0, Xs, Set)' is true iff `Set' is the relative
	% complement of `Set0' and the set containing only the members of
	% `Xs'.

:- pred set__delete_list(set(T)::in, list(T)::in, set(T)::out) is det.

	% XXX rwab1: I think we should reverse the args. here for
	% higher order programming.
:- func set__delete_list(set(T), list(T)) = set(T).

	% `set__remove(Set0, X, Set)' is true iff `Set0' contains `X',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only `X', i.e.  if `Set' is the set which contains
	% all the elements of `Set0' except `X'.

:- pred set__remove(set(T)::in, T::in, set(T)::out) is semidet.

	% `set__remove_list(Set0, Xs, Set)' is true iff `Xs' does not
	% contain any duplicates, `Set0' contains every member of `Xs',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only the members of `Xs'.

:- pred set__remove_list(set(T)::in, list(T)::in, set(T)::out) is semidet.

	% `set__remove_least(Set0, Elem, Set)' is true iff
	% `Set0' is not empty, `Elem' is the smallest element in `Set0'
	% (with elements ordered using the standard ordering given
	% by compare/3), and `Set' is the set containing all the
	% elements of `Set0' except `Elem'.

:- pred set__remove_least(set(T)::in, T::out, set(T)::out) is semidet.

	% `set_union(SetA, SetB, Set)' is true iff `Set' is the union of
	% `SetA' and `SetB'.  If the sets are known to be of different
	% sizes, then for efficiency make `SetA' the larger of the two.
	% (The current implementation using sorted lists with duplicates
	% removed is not sensitive to the ordering of the input arguments,
	% but other set implementations may be, so observing this convention
	% will make it less likely that you will encounter problems if
	% the implementation is changed.)

:- pred set__union(set(T)::in, set(T)::in, set(T)::out) is det.
:- func set__union(set(T), set(T)) = set(T).

	% `set__union_list(A, B)' is true iff `B' is the union of
	% all the sets in `A'
:- func set__union_list(list(set(T))) = set(T).

	% `set__power_union(A, B)' is true iff `B' is the union of
	% all the sets in `A'

:- pred set__power_union(set(set(T))::in, set(T)::out) is det.
:- func set__power_union(set(set(T))) = set(T).

	% `set__intersect(SetA, SetB, Set)' is true iff `Set' is the
	% intersection of `SetA' and `SetB'. If the two sets are
	% known to be unequal in size, then making SetA be the larger
	% set will usually be more efficient.
	% (The current implementation, using sorted lists with duplicates
	% removed is not sensitive to the ordering of the input arguments
	% but other set implementations may be, so observing this convention
	% will make it less likely that you will encounter problems if
	% the implementation is changed.)

:- pred set__intersect(set(T)::in, set(T)::in, set(T)::out) is det.
:- func set__intersect(set(T), set(T)) = set(T).

	% `set__power_intersect(A, B)' is true iff `B' is the intersection of
	% all the sets in `A'

:- pred set__power_intersect(set(set(T))::in, set(T)::out) is det.
:- func set__power_intersect(set(set(T))) = set(T).

	% `set__intersect_list(A, B)' is true iff `B' is the intersection of
	% all the sets in `A'

:- func set__intersect_list(list(set(T))) = set(T).

	% `set__difference(SetA, SetB, Set)' is true iff `Set' is the
	% set containing all the elements of `SetA' except those that
	% occur in `SetB'

:- pred set__difference(set(T)::in, set(T)::in, set(T)::out) is det.
:- func set__difference(set(T), set(T)) = set(T).

	% `set__count(Set, Count)' is true iff `Set' has `Count' elements.

:- pred set__count(set(T)::in, int::out) is det.
:- func set__count(set(T)) = int.

	% Support for higher order set processing.

	% map(F, S) =
	% 	list_to_set(list__map(F, to_sorted_list(S))).
	%
:- func set__map(func(T1) = T2, set(T1)) = set(T2).

	% set__map_fold(P, S0, S, A0, A) :-
	%	L0 = set__to_sorted_list(S0),
	%	list__map_foldl(P, L0, L, A0, A),
	%	S = set__list_to_set(L).
:- pred set__map_fold(pred(T1, T2, T3, T3), set(T1), set(T2), T3, T3).
:- mode set__map_fold(pred(in, out, in, out) is det, in, out, in, out) is det.

	% set__filter(P, S) =
	% 	sorted_list_to_set(list__filter(P, to_sorted_list(S))).
	%
:- func set__filter(pred(T1), set(T1)) = set(T1).
:- mode set__filter(pred(in) is semidet, in) = out is det.

	% set__filter_map(PF, S) =
	% 	list_to_set(list__filter_map(PF, to_sorted_list(S))).
	%
:- func set__filter_map(func(T1) = T2, set(T1)) = set(T2).
:- mode set__filter_map(func(in) = out is semidet, in) = out is det.

	% set__fold(F, S, A) =
	% 	list__foldl(F, to_sorted_list(S), A).
	%
:- func set__fold(func(T1, T2) = T2, set(T1), T2) = T2.

:- pred set__fold(pred(T1, T2, T2), set(T1), T2, T2).
:- mode set__fold(pred(in, in, out) is det, in, in, out) is det.
:- mode set__fold(pred(in, di, uo) is det, in, di, uo) is det.
:- mode set__fold(pred(in, in, out) is semidet, in, in, out) is semidet.

	% set__divide(Pred, Set, TruePart, FalsePart):
	% TruePart consists of those elements of Set for which Pred succeeds;
	% FalsePart consists of those elements of Set for which Pred fails.
	%
:- pred set__divide(pred(T1), set(T1), set(T1), set(T1)).
:- mode set__divide(pred(in) is semidet, in, out, out) is det.

%--------------------------------------------------%


Node:set_bbbtree, Next:, Previous:set, Up:Top

49 set_bbbtree


%--------------------------------------------------%
% Copyright (C) 1995-1997, 1999-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: set_bbbtree.m.
% Main authors: benyi.
% Stability: low.

% set_bbbtree - implements sets using bounded balanced binary trees.

%--------------------------------------------------%

:- module set_bbbtree.

:- interface.

:- import_module bool, list.

:- type set_bbbtree(T).

	% `set_bbbtree__init(Set)' returns an initialized empty set.

:- pred set_bbbtree__init(set_bbbtree(T)::uo) is det.
:- func set_bbbtree__init = set_bbbtree(T).

        % `set_bbbtree__empty(Set) is true iff `Set' is contains no elements.

:- pred set_bbbtree__empty(set_bbbtree(T)::in) is semidet.

	% `set_bbbtree__size(Set, Size)' is true iff `Size' is the cardinality
	% of `Set'.

:- pred set_bbbtree__size(set_bbbtree(T)::in, int::out) is det.

	% `set_bbbtree__member(X, Set)' is true iff `X' is a member of `Set'.
	% O(lg n) for (in, in) and O(1) for (out, in).

:- pred set_bbbtree__member(T, set_bbbtree(T)).
:- mode set_bbbtree__member(in, in) is semidet.
:- mode set_bbbtree__member(out, in) is nondet.

	% `set_bbbtree__is_member(X, Set, Result)' is true iff `X' is a member
	% of `Set'.

:- pred set_bbbtree__is_member(T::in, set_bbbtree(T)::in, bool::out) is det.

	% `set_bbbtree__contains(Set, X)' is true iff `X' is a member of `Set'.
	% O(lg n).

:- pred set_bbbtree__contains(set_bbbtree(T)::in, T::in) is semidet.

	% `set_bbbtree__least(Set, X)' is true iff `X' is smaller than all
	% the other members of `Set'.

:- pred set_bbbtree__least(set_bbbtree(T), T).
:- mode set_bbbtree__least(in, out) is semidet.
:- mode set_bbbtree__least(in, in) is semidet.

	% `set_bbbtree__largest(Set, X)' is true iff `X' is larger than all
	% the other members of `Set'.

:- pred set_bbbtree__largest(set_bbbtree(T), T).
:- mode set_bbbtree__largest(in, out) is semidet.
:- mode set_bbbtree__largest(in, in) is semidet.

	% `set_bbbtree__singleton_set(Set, X)' is true iff `Set' is the set
	% containing just the single element `X'.

:- pred set_bbbtree__singleton_set(set_bbbtree(T), T).
:- mode set_bbbtree__singleton_set(uo, di) is det.
:- mode set_bbbtree__singleton_set(in, out) is semidet.
:- mode set_bbbtree__singleton_set(in, in) is semidet.
:- mode set_bbbtree__singleton_set(out, in) is det.

:- func set_bbbtree__make_singleton_set(T) = set_bbbtree(T).

	% `set_bbbtree__equal(SetA, SetB)' is true iff `SetA' and `SetB'
	% contain the same elements.

:- pred set_bbbtree__equal(set_bbbtree(T)::in, set_bbbtree(T)::in) is semidet.

	% `set_bbbtree__insert(Set0, X, Set)' is true iff `Set' is the union of
	% `Set0' and the set containing only `X'.

:- pred set_bbbtree__insert(set_bbbtree(T), T, set_bbbtree(T)).
:- mode set_bbbtree__insert(di, di, uo) is det.
:- mode set_bbbtree__insert(in, in, out) is det.

:- func set_bbbtree__insert(set_bbbtree(T), T) = set_bbbtree(T).

	% `set_bbbtree__insert_list(Set0, Xs, Set)' is true iff `Set' is
	% the union of `Set0' and the set containing only the members of `Xs'.

:- pred set_bbbtree__insert_list(set_bbbtree(T)::in, list(T)::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__insert_list(set_bbbtree(T), list(T)) = set_bbbtree(T).

	% `set_bbbtree__delete(Set0, X, Set)' is true iff `Set' is the relative
	% complement of `Set0' and the set containing only `X', i.e.
	% if `Set' is the set which contains all the elements of `Set0'
	% except `X'.

:- pred set_bbbtree__delete(set_bbbtree(T), T, set_bbbtree(T)).
:- mode set_bbbtree__delete(di, in, uo) is det.
:- mode set_bbbtree__delete(in, in, out) is det.

:- func set_bbbtree__delete(set_bbbtree(T), T) = set_bbbtree(T).

	% `set_bbbtree__delete_list(Set0, Xs, Set)' is true iff `Set' is the
	% relative complement of `Set0' and the set containing only the members
	% of `Xs'.

:- pred set_bbbtree__delete_list(set_bbbtree(T)::in, list(T)::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__delete_list(set_bbbtree(T), list(T)) = set_bbbtree(T).

	% `set_bbbtree__remove(Set0, X, Set)' is true iff `Set0' contains `X',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only `X', i.e.  if `Set' is the set which contains
	% all the elements of `Set0' except `X'.

:- pred set_bbbtree__remove(set_bbbtree(T)::in, T::in, set_bbbtree(T)::out)
	is semidet.

	% `set_bbbtree__remove_list(Set0, Xs, Set)' is true iff Xs does not
	% contain any duplicates, `Set0' contains every member of `Xs',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only the members of `Xs'.

:- pred set_bbbtree__remove_list(set_bbbtree(T)::in, list(T)::in,
	set_bbbtree(T)::out) is semidet.

	% `set_bbbtree__remove_least(Set0, X, Set)' is true iff the union if
	% `X' and `Set' is `Set0' and `X' is smaller than all the elements of
	% `Set'.

:- pred set_bbbtree__remove_least(set_bbbtree(T)::in, T::out,
	set_bbbtree(T)::out) is semidet.

	% `set_bbbtree__remove_largest(Set0, X, Set)' is true iff the union if
	% `X' and `Set' is `Set0' and `X' is larger than all the elements of
	% `Set'.

:- pred set_bbbtree__remove_largest(set_bbbtree(T)::in, T::out,
	set_bbbtree(T)::out) is semidet.

	% `set_bbbtree__list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'. O(n lg n)

:- pred set_bbbtree__list_to_set(list(T)::in, set_bbbtree(T)::out) is det.

:- func set_bbbtree__list_to_set(list(T)) = set_bbbtree(T).

	% `set_bbbtree__sorted_list_to_set(List, Set)' is true iff `Set' is the
	% set containing only the members of `List'.
	% `List' must be sorted. O(n).

:- pred set_bbbtree__sorted_list_to_set(list(T)::in, set_bbbtree(T)::out)
	is det.

:- func set_bbbtree__sorted_list_to_set(list(T)) = set_bbbtree(T).

	% `set_bbbtree__sorted_list_to_set_len(List, Set, N)' is true iff
	% `Set' is the set set containing only the members of `List' and `N'
	% is the length of the list. If the length of the list is already known
	% then a noticable speed improvement can be expected over
	% `set_bbbtree__sorted_list_to_set' as a significant cost involved
	% with `set_bbbtree__sorted_list_to_set' is the call to list__length.
	% `List' must be sorted. O(n).

:- pred set_bbbtree__sorted_list_to_set_len(list(T)::in, set_bbbtree(T)::out,
	int::in) is det.

	% `set_bbbtree__to_sorted_list(Set, List)' is true iff `List' is the
	% list of all the members of `Set', in sorted order. O(n).

:- pred set_bbbtree__to_sorted_list(set_bbbtree(T), list(T)).
:- mode set_bbbtree__to_sorted_list(di, uo) is det.
:- mode set_bbbtree__to_sorted_list(in, out) is det.

:- func set_bbbtree__to_sorted_list(set_bbbtree(T)) = list(T).

	% `set_bbbtree__union(SetA, SetB, Set)' is true iff `Set' is the union
	% of `SetA' and `SetB'.

:- pred set_bbbtree__union(set_bbbtree(T)::in, set_bbbtree(T)::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__union(set_bbbtree(T), set_bbbtree(T)) = set_bbbtree(T).

	% `set_bbbtree__union_list(Sets) = Set' is true iff `Set' is the union
	% of all the sets in `Sets'

:- func set_bbbtree__union_list(list(set_bbbtree(T))) = set_bbbtree(T).

	% `set_bbbtree__power_union(Sets, Set)' is true iff `Set' is the union
	% of all the sets in `Sets'

:- pred set_bbbtree__power_union(set_bbbtree(set_bbbtree(T))::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__power_union(set_bbbtree(set_bbbtree(T))) = set_bbbtree(T).

	% `set_bbbtree__intersect(SetA, SetB, Set)' is true iff `Set' is the
	% intersection of `SetA' and `SetB'.

:- pred set_bbbtree__intersect(set_bbbtree(T)::in, set_bbbtree(T)::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__intersect(set_bbbtree(T), set_bbbtree(T)) = set_bbbtree(T).

	% `set_bbbtree__power_intersect(Sets, Set) is true iff `Set' is the
	% intersection of the sets in `Sets'.

:- pred set_bbbtree__power_intersect(set_bbbtree(set_bbbtree(T))::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__power_intersect(set_bbbtree(set_bbbtree(T)))
	= set_bbbtree(T).

	% `set_bbbtree__intersect_list(Sets) = Set is true iff `Set' is the
	% intersection of the sets in `Sets'.

:- func set_bbbtree__intersect_list(list(set_bbbtree(T))) = set_bbbtree(T).

	% `set_bbtree__difference(SetA, SetB, Set)' is true iff `Set' is the
	%  set containing all the elements of `SetA' except those that
	% occur in `SetB'.

:- pred set_bbbtree__difference(set_bbbtree(T)::in, set_bbbtree(T)::in,
	set_bbbtree(T)::out) is det.

:- func set_bbbtree__difference(set_bbbtree(T), set_bbbtree(T))
		= set_bbbtree(T).

	% `set_bbbtree__subset(SetA, SetB)' is true iff all the elements of
	% `SetA' are also elements of `SetB'.

:- pred set_bbbtree__subset(set_bbbtree(T)::in, set_bbbtree(T)::in) is semidet.

	% `set_bbbtree__superset(SetA, SetB)' is true iff all the elements of
	% `SetB' are also elements of `SetA'.

:- pred set_bbbtree__superset(set_bbbtree(T)::in, set_bbbtree(T)::in)
	is semidet.

:- func set_bbbtree__map(func(T1) = T2, set_bbbtree(T1)) = set_bbbtree(T2).

:- func set_bbbtree__filter_map(func(T1) = T2, set_bbbtree(T1))
	= set_bbbtree(T2).
:- mode set_bbbtree__filter_map(func(in) = out is semidet, in) = out is det.

:- func set_bbbtree__fold(func(T1, T2) = T2, set_bbbtree(T1), T2) = T2.

%--------------------------------------------------%
%--------------------------------------------------%


Node:set_ordlist, Next:, Previous:set_bbbtree, Up:Top

50 set_ordlist


%--------------------------------------------------%
% Copyright (C) 1996-1997,1999-2002, 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: set_ordlist.m.
% Main authors: conway, fjh.
% Stability: medium.

% This file contains a `set' ADT.
% Sets are implemented here as sorted lists without duplicates.

%--------------------------------------------------%

:- module set_ordlist.
:- interface.
:- import_module bool, list.

:- type set_ordlist(_T).

	% `set_ordlist__list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'.

:- pred set_ordlist__list_to_set(list(T)::in, set_ordlist(T)::out) is det.
:- func set_ordlist__list_to_set(list(T)) = set_ordlist(T).

	% `set_ordlist__sorted_list_to_set(List, Set)' is true iff `Set' is
	% the set containing only the members of `List'.  `List' must be sorted.

:- pred set_ordlist__sorted_list_to_set(list(T)::in, set_ordlist(T)::out)
	is det.
:- func set_ordlist__sorted_list_to_set(list(T)) = set_ordlist(T).

	% `set_ordlist__to_sorted_list(Set, List)' is true iff `List' is the
	% list of all the members of `Set', in sorted order.

:- pred set_ordlist__to_sorted_list(set_ordlist(T)::in, list(T)::out) is det.
:- func set_ordlist__to_sorted_list(set_ordlist(T)) = list(T).

	% `set_ordlist__init(Set)' is true iff `Set' is an empty set.

:- pred set_ordlist__init(set_ordlist(_T)::uo) is det.
:- func set_ordlist__init = set_ordlist(T).

	% `set_ordlist__singleton_set(Set, Elem)' is true iff `Set' is the set
	% containing just the single element `Elem'.

:- pred set_ordlist__singleton_set(set_ordlist(T), T).
:- mode set_ordlist__singleton_set(in, out) is semidet.
:- mode set_ordlist__singleton_set(out, in) is det.

:- func set_ordlist__make_singleton_set(T) = set_ordlist(T).

	% `set_ordlist__equal(SetA, SetB)' is true iff
	% `SetA' and `SetB' contain the same elements.

:- pred set_ordlist__equal(set_ordlist(T)::in, set_ordlist(T)::in) is semidet.

	% `set_ordlist__empty(Set)' is true iff `Set' is an empty set.

:- pred set_ordlist__empty(set_ordlist(_T)::in) is semidet.

	% `set_ordlist__subset(SetA, SetB)' is true iff `SetA' is a subset of
	% `SetB'.

:- pred set_ordlist__subset(set_ordlist(T)::in, set_ordlist(T)::in) is semidet.

	% `set_ordlist__superset(SetA, SetB)' is true iff `SetA' is a
	% superset of `SetB'.

:- pred set_ordlist__superset(set_ordlist(T)::in, set_ordlist(T)::in)
	is semidet.

	% `set_ordlist__member(X, Set)' is true iff `X' is a member of `Set'.

:- pred set_ordlist__member(T, set_ordlist(T)).
:- mode set_ordlist__member(in, in) is semidet.
:- mode set_ordlist__member(out, in) is nondet.

	% `set_ordlist__is_member(X, Set, Result)' returns
	% `Result = yes' iff `X' is a member of `Set'.

:- pred set_ordlist__is_member(T::in, set_ordlist(T)::in, bool::out) is det.

	% `set_ordlist__contains(Set, X)' is true iff `X' is a member of `Set'.

:- pred set_ordlist__contains(set_ordlist(T)::in, T::in) is semidet.

	% `set_ordlist__insert(Set0, X, Set)' is true iff `Set' is the union
	% of `Set0' and the set containing only `X'.

:- pred set_ordlist__insert(set_ordlist(T), T, set_ordlist(T)).
:- mode set_ordlist__insert(di, di, uo) is det.
:- mode set_ordlist__insert(in, in, out) is det.

:- func set_ordlist__insert(set_ordlist(T), T) = set_ordlist(T).

	% `set_ordlist__insert_list(Set0, Xs, Set)' is true iff `Set' is the
	% union of `Set0' and the set containing only the members of `Xs'.

:- pred set_ordlist__insert_list(set_ordlist(T)::in, list(T)::in,
	set_ordlist(T)::out) is det.
:- func set_ordlist__insert_list(set_ordlist(T), list(T)) = set_ordlist(T).

	% `set_ordlist__delete(Set0, X, Set)' is true iff `Set' is the
	% relative complement of `Set0' and the set containing only `X', i.e.
	% if `Set' is the set which contains all the elements of `Set0'
	% except `X'.

:- pred set_ordlist__delete(set_ordlist(T)::in, T::in, set_ordlist(T)::out)
	is det.
:- func set_ordlist__delete(set_ordlist(T), T) = set_ordlist(T).

	% `set_ordlist__delete_list(Set0, Xs, Set)' is true iff `Set' is the
	% relative complement of `Set0' and the set containing only the members
	% of `Xs'.

:- pred set_ordlist__delete_list(set_ordlist(T)::in, list(T)::in,
	set_ordlist(T)::out) is det.
:- func set_ordlist__delete_list(set_ordlist(T), list(T)) = set_ordlist(T).

	% `set_ordlist__remove(Set0, X, Set)' is true iff `Set0' contains `X',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only `X', i.e.  if `Set' is the set which contains
	% all the elements of `Set0' except `X'.

:- pred set_ordlist__remove(set_ordlist(T)::in, T::in, set_ordlist(T)::out)
	is semidet.

	% `set_ordlist__remove_list(Set0, Xs, Set)' is true iff Xs does not
	% contain any duplicates, `Set0' contains every member of `Xs',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only the members of `Xs'.

:- pred set_ordlist__remove_list(set_ordlist(T)::in, list(T)::in,
	set_ordlist(T)::out) is semidet.

	% `set_ordlist__remove_least(Set0, X, Set)' is true iff `X' is the
	% least element in `Set0', and `Set' is the set which contains all the
	% elements of `Set0' except `X'.

:- pred set_ordlist__remove_least(set_ordlist(T)::in, T::out,
	set_ordlist(T)::out) is semidet.

	% `set_ordlist_union(SetA, SetB, Set)' is true iff `Set' is the union
	% of `SetA' and `SetB'. The efficiency of the union operation is
	% O(card(SetA)+card(SetB)) and is not sensitive to the argument
	% ordering.

:- pred set_ordlist__union(set_ordlist(T)::in, set_ordlist(T)::in,
	set_ordlist(T)::out) is det.

:- func set_ordlist__union(set_ordlist(T), set_ordlist(T)) = set_ordlist(T).

	% `set_ordlist__union_list(A, B)' is true iff `B' is the union of
	% all the sets in `A'

:- func set_ordlist__union_list(list(set_ordlist(T))) = set_ordlist(T).

	% `set_ordlist__power_union(A, B)' is true iff `B' is the union of
	% all the sets in `A'

:- pred set_ordlist__power_union(set_ordlist(set_ordlist(T))::in,
	set_ordlist(T)::out) is det.

:- func set_ordlist__power_union(set_ordlist(set_ordlist(T))) = set_ordlist(T).

	% `set_ordlist__intersect(SetA, SetB, Set)' is true iff `Set' is the
	% intersection of `SetA' and `SetB'. The efficiency of the intersection
	% operation is not influenced by the argument order.

:- pred set_ordlist__intersect(set_ordlist(T), set_ordlist(T), set_ordlist(T)).
:- mode set_ordlist__intersect(in, in, out) is det.
:- mode set_ordlist__intersect(in, in, in) is semidet.

:- func set_ordlist__intersect(set_ordlist(T), set_ordlist(T))
	= set_ordlist(T).

	% `set_ordlist__power_intersect(A, B)' is true iff `B' is the
	% intersection of all the sets in `A'.

:- pred set_ordlist__power_intersect(set_ordlist(set_ordlist(T))::in,
	set_ordlist(T)::out) is det.
:- func set_ordlist__power_intersect(set_ordlist(set_ordlist(T)))
	= set_ordlist(T).

	% `set_ordlist__intersect_list(A, B)' is true iff `B' is the
	% intersection of all the sets in `A'.

:- func set_ordlist__intersect_list(list(set_ordlist(T))) = set_ordlist(T).

	% `set_ordlist__difference(SetA, SetB, Set)' is true iff `Set' is the
	% set containing all the elements of `SetA' except those that
	% occur in `SetB'.

:- pred set_ordlist__difference(set_ordlist(T)::in, set_ordlist(T)::in,
	set_ordlist(T)::out) is det.
:- func set_ordlist__difference(set_ordlist(T), set_ordlist(T))
	= set_ordlist(T).

	% `set_ordlist__count(Set, Count)' is true iff `Set' has
	% `Count' elements.

:- pred set_ordlist__count(set_ordlist(T)::in, int::out) is det.
:- func set_ordlist__count(set_ordlist(T)) = int.

:- func set_ordlist__map(func(T1) = T2, set_ordlist(T1)) = set_ordlist(T2).

:- func set_ordlist__filter_map(func(T1) = T2, set_ordlist(T1))
	= set_ordlist(T2).
:- mode set_ordlist__filter_map(func(in) = out is semidet, in) = out is det.

:- func set_ordlist__fold(func(T1, T2) = T2, set_ordlist(T1), T2) = T2.

	% set_ordlist__divide(Pred, Set, TruePart, FalsePart):
	% TruePart consists of those elements of Set for which Pred succeeds;
	% FalsePart consists of those elements of Set for which Pred fails.
:- pred set_ordlist__divide(pred(T1)::in(pred(in) is semidet),
	set_ordlist(T1)::in, set_ordlist(T1)::out, set_ordlist(T1)::out)
	is det.

%--------------------------------------------------%


Node:set_unordlist, Next:, Previous:set_ordlist, Up:Top

51 set_unordlist


%--------------------------------------------------%
% Copyright (C) 1995-1997,1999-2002, 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: set_unordlist.m.
% Main authors: conway, fjh.
% Stability: medium.

% This file contains a `set' ADT.
% Sets are implemented here as unsorted lists, which may contain duplicates.

%--------------------------------------------------%

:- module set_unordlist.
:- interface.
:- import_module bool, list.

:- type set_unordlist(_T).

	% `set_unordlist__list_to_set(List, Set)' is true iff `Set' is the set
	% containing only the members of `List'.

:- pred set_unordlist__list_to_set(list(T)::in, set_unordlist(T)::out) is det.
:- func set_unordlist__list_to_set(list(T)) = set_unordlist(T).

	% `set_unordlist__sorted_list_to_set(List, Set)' is true iff `Set' is
	% the set containing only the members of `List'.  `List' must be sorted.

:- pred set_unordlist__sorted_list_to_set(list(T)::in, set_unordlist(T)::out)
	is det.
:- func set_unordlist__sorted_list_to_set(list(T)) = set_unordlist(T).

	% `set_unordlist__to_sorted_list(Set, List)' is true iff `List' is the
	% list of all the members of `Set', in sorted order.

:- pred set_unordlist__to_sorted_list(set_unordlist(T)::in, list(T)::out)
	is det.
:- func set_unordlist__to_sorted_list(set_unordlist(T)) = list(T).

	% `set_unordlist__init(Set)' is true iff `Set' is an empty set.

:- pred set_unordlist__init(set_unordlist(_T)::uo) is det.
:- func set_unordlist__init = set_unordlist(T).

	% `set_unordlist__singleton_set(Set, Elem)' is true iff `Set' is the set
	% containing just the single element `Elem'.

:- pred set_unordlist__singleton_set(set_unordlist(T), T).
:- mode set_unordlist__singleton_set(in, out) is semidet.
:- mode set_unordlist__singleton_set(out, in) is det.

:- func set_unordlist__make_singleton_set(T) = set_unordlist(T).

	% `set_unordlist__equal(SetA, SetB)' is true iff
	% `SetA' and `SetB' contain the same elements.

:- pred set_unordlist__equal(set_unordlist(T)::in, set_unordlist(T)::in)
	is semidet.

	% `set_unordlist__empty(Set)' is true iff `Set' is an empty set.

:- pred set_unordlist__empty(set_unordlist(_T)::in) is semidet.

	% `set_unordlist__subset(SetA, SetB)' is true iff `SetA' is a subset of
	% `SetB'.

:- pred set_unordlist__subset(set_unordlist(T)::in, set_unordlist(T)::in)
	is semidet.

	% `set_unordlist__superset(SetA, SetB)' is true iff `SetA' is a
	% superset of `SetB'.

:- pred set_unordlist__superset(set_unordlist(T)::in, set_unordlist(T)::in)
	is semidet.

	% `set_unordlist__member(X, Set)' is true iff `X' is a member of `Set'.

:- pred set_unordlist__member(T, set_unordlist(T)).
:- mode set_unordlist__member(in, in) is semidet.
:- mode set_unordlist__member(out, in) is nondet.

	% `set_unordlist__is_member(X, Set, Result)' returns
	% `Result = yes' iff `X' is a member of `Set'.

:- pred set_unordlist__is_member(T::in, set_unordlist(T)::in, bool::out)
	is det.

	% `set_unordlist__contains(Set, X)' is true iff
	% `X' is a member of `Set'.

:- pred set_unordlist__contains(set_unordlist(T)::in, T::in) is semidet.

	% `set_unordlist__insert(Set0, X, Set)' is true iff `Set' is the union
	% of `Set0' and the set containing only `X'.

:- pred set_unordlist__insert(set_unordlist(T), T, set_unordlist(T)).
:- mode set_unordlist__insert(di, di, uo) is det.
:- mode set_unordlist__insert(in, in, out) is det.

:- func set_unordlist__insert(set_unordlist(T), T) = set_unordlist(T).

	% `set_unordlist__insert_list(Set0, Xs, Set)' is true iff `Set' is the
	% union of `Set0' and the set containing only the members of `Xs'.

:- pred set_unordlist__insert_list(set_unordlist(T)::in, list(T)::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__insert_list(set_unordlist(T), list(T))
	= set_unordlist(T).

	% `set_unordlist__delete(Set0, X, Set)' is true iff `Set' is the
	% relative complement of `Set0' and the set containing only `X', i.e.
	% if `Set' is the set which contains all the elements of `Set0'
	% except `X'.

:- pred set_unordlist__delete(set_unordlist(T), T, set_unordlist(T)).
:- mode set_unordlist__delete(di, in, uo) is det.
:- mode set_unordlist__delete(in, in, out) is det.

:- func set_unordlist__delete(set_unordlist(T), T) = set_unordlist(T).

	% `set_unordlist__delete_list(Set0, Xs, Set)' is true iff `Set' is the
	% relative complement of `Set0' and the set containing only the members
	% of `Xs'.

:- pred set_unordlist__delete_list(set_unordlist(T)::in, list(T)::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__delete_list(set_unordlist(T), list(T))
	= set_unordlist(T).

	% `set_unordlist__remove(Set0, X, Set)' is true iff `Set0' contains `X',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only `X', i.e.  if `Set' is the set which contains
	% all the elements of `Set0' except `X'.

:- pred set_unordlist__remove(set_unordlist(T)::in, T::in,
	set_unordlist(T)::out) is semidet.

	% `set_unordlist__remove_list(Set0, Xs, Set)' is true iff Xs does not
	% contain any duplicates, `Set0' contains every member of `Xs',
	% and `Set' is the relative complement of `Set0' and the set
	% containing only the members of `Xs'.

:- pred set_unordlist__remove_list(set_unordlist(T)::in, list(T)::in,
	set_unordlist(T)::out) is semidet.

	% `set_unordlist__remove_least(Set0, X, Set)' is true iff `X' is the
	% least element in `Set0', and `Set' is the set which contains all the
	% elements of `Set0' except `X'.

:- pred set_unordlist__remove_least(set_unordlist(T)::in, T::out,
	set_unordlist(T)::out) is semidet.

	% `set_unordlist_union(SetA, SetB, Set)' is true iff `Set' is the union
	% of `SetA' and `SetB'.  If the sets are known to be of different
	% sizes, then for efficiency make `SetA' the larger of the two.

:- pred set_unordlist__union(set_unordlist(T)::in, set_unordlist(T)::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__union(set_unordlist(T), set_unordlist(T))
	= set_unordlist(T).

	% `set_unordlist__union_list(A) = B' is true iff `B' is the union of
	% all the sets in `A'

:- func set_unordlist__union_list(list(set_unordlist(T))) = set_unordlist(T).

	% `set_unordlist__power_union(A, B)' is true iff `B' is the union of
	% all the sets in `A'

:- pred set_unordlist__power_union(set_unordlist(set_unordlist(T))::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__power_union(set_unordlist(set_unordlist(T)))
	= set_unordlist(T).

	% `set_unordlist__intersect(SetA, SetB, Set)' is true iff `Set' is the
	% intersection of `SetA' and `SetB'.

:- pred set_unordlist__intersect(set_unordlist(T)::in, set_unordlist(T)::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__intersect(set_unordlist(T), set_unordlist(T))
	= set_unordlist(T).

	% `set_unordlist__power_intersect(A, B)' is true iff `B' is the
	% intersection of all the sets in `A'

:- pred set_unordlist__power_intersect(set_unordlist(set_unordlist(T))::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__power_intersect(set_unordlist(set_unordlist(T)))
	= set_unordlist(T).

	% `set_unordlist__intersect_list(A, B)' is true iff `B' is the
	% intersection of all the sets in `A'

:- func set_unordlist__intersect_list(list(set_unordlist(T)))
	= set_unordlist(T).

	% `set_unordlist__difference(SetA, SetB, Set)' is true iff `Set' is the
	% set containing all the elements of `SetA' except those that
	% occur in `SetB'

:- pred set_unordlist__difference(set_unordlist(T)::in, set_unordlist(T)::in,
	set_unordlist(T)::out) is det.

:- func set_unordlist__difference(set_unordlist(T), set_unordlist(T))
	= set_unordlist(T).

:- func set_unordlist__map(func(T1) = T2, set_unordlist(T1))
	= set_unordlist(T2).

:- func set_unordlist__filter_map(func(T1) = T2, set_unordlist(T1))
	= set_unordlist(T2).
:- mode set_unordlist__filter_map(func(in) = out is semidet, in) = out is det.

:- func set_unordlist__fold(func(T1, T2) = T2, set_unordlist(T1), T2) = T2.

	% set_unordlist__divide(Pred, Set, TruePart, FalsePart):
	% TruePart consists of those elements of Set for which Pred succeeds;
	% FalsePart consists of those elements of Set for which Pred fails.
:- pred set_unordlist__divide(pred(T1), set_unordlist(T1), set_unordlist(T1),
	set_unordlist(T1)).
:- mode set_unordlist__divide(pred(in) is semidet, in, out, out) is det.

%--------------------------------------------------%


Node:sparse_bitset, Next:, Previous:set_unordlist, Up:Top

52 sparse_bitset


%--------------------------------------------------%
% Copyright (C) 2000-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: sparse_bitset.m.
% Author: stayl
% Stability: medium.
%
% This module provides an ADT for storing sets of integers.
% If the integers stored are closely grouped, a sparse_bitset
% is much more compact than the representation provided by set.m,
% and the operations will be much faster.
%
%
% Efficiency notes:
%
% A sparse bitset is represented as a sorted list of pairs of integers.
% For a pair `Offset - Bits', `Offset' is a multiple of `int__bits_per_int'.
% The bits of `Bits' describe which of the elements of the range
% `Offset' .. `Offset + bits_per_int - 1' are in the set.
% Pairs with the same value of `Offset' are merged.
% Pairs for which `Bits' is zero are removed.
%
% The values of `Offset' in the list need not be contiguous multiples
% of `bits_per_int', hence the name _sparse_ bitset.
%
% A sparse_bitset is suitable for storing sets of integers which
% can be represented using only a few `Offset - Bits' pairs.
% In the worst case, where the integers stored are not closely
% grouped, a sparse_bitset will take more memory than an
% ordinary set, but the operations should not be too much slower.
%
% In the asymptotic complexities of the operations below,
% `rep_size(Set)' is the number of pairs needed to represent `Set',
% and `card(Set)' is the number of elements in `Set'.
%
%--------------------------------------------------%
%--------------------------------------------------%
:- module sparse_bitset.

:- interface.

:- import_module enum, list, term.
:- use_module set.

:- type sparse_bitset(T). % <= enum(T).

	% Return an empty set.
:- func init = sparse_bitset(T).

:- pred init(sparse_bitset(T)).
:- mode init(out) is det.

:- pred empty(sparse_bitset(T)).
:- mode empty(in) is semidet.
:- mode empty(out) is det.

	% `equal(SetA, SetB' is true iff `SetA' and `SetB'
	% contain the same elements.
	% Takes O(min(rep_size(SetA), rep_size(SetB))) time.
:- pred equal(sparse_bitset(T), sparse_bitset(T)).
:- mode equal(in, in) is semidet.

	% `list_to_set(List)' returns a set
	% containing only the members of `List'.
	% In the worst case this will take O(length(List)^2) time
	% and space. If the elements of the list are closely
	% grouped, it will be closer to O(length(List)).
:- func list_to_set(list(T)) = sparse_bitset(T) <= enum(T).

:- pred list_to_set(list(T), sparse_bitset(T)) <= enum(T).
:- mode list_to_set(in, out) is det.

	% `sorted_list_to_set(List)' returns a set containing
	% only the members of `List'.
	% `List' must be sorted.
	% Takes O(length(List)) time and space.
:- func sorted_list_to_set(list(T)) = sparse_bitset(T) <= enum(T).

:- pred sorted_list_to_set(list(T), sparse_bitset(T)) <= enum(T).
:- mode sorted_list_to_set(in, out) is det.

	% `sorted_list_to_set(Set)' returns a bitset containing
	% only the members of `Set'.
	% `List' must be sorted.
	% Takes O(card(Set)) time and space.
:- func from_set(set.set(T)) = sparse_bitset(T) <= enum(T).

	% `to_sorted_list(Set)' returns a list
	% containing all the members of `Set', in sorted order.
	% Takes O(card(Set)) time and space.
:- func to_sorted_list(sparse_bitset(T)) = list(T) <= enum(T).

:- pred to_sorted_list(sparse_bitset(T), list(T)) <= enum(T).
:- mode to_sorted_list(in, out) is det.

	% `to_sorted_list(Set)' returns a set.set containing all
	% the members of `Set', in sorted order.
	% Takes O(card(Set)) time and space.
:- func to_set(sparse_bitset(T)) = set.set(T) <= enum(T).

	% `make_singleton_set(Elem)' returns a set
	% containing just the single element `Elem'.
:- func make_singleton_set(T) = sparse_bitset(T) <= enum(T).

	% Note: set.m contains the reverse mode of this predicate,
	% but it is difficult to implement both modes using
	% the representation in this module.
:- pred singleton_set(sparse_bitset(T), T) <= enum(T).
:- mode singleton_set(out, in) is det.

	% `subset(Subset, Set)' is true iff `Subset' is a subset of `Set'.
	% Same as `intersect(Set, Subset, Subset)', but may be more efficient.
:- pred subset(sparse_bitset(T), sparse_bitset(T)).
:- mode subset(in, in) is semidet.

	% `superset(Superset, Set)' is true iff `Superset' is a
	% superset of `Set'.
	% Same as `intersect(Superset, Set, Set)', but may be more efficient.
:- pred superset(sparse_bitset(T), sparse_bitset(T)).
:- mode superset(in, in) is semidet.

        % `contains(Set, X)' is true iff `X' is a member of `Set'.
	% Takes O(rep_size(Set)) time.
:- pred contains(sparse_bitset(T), T) <= enum(T).
:- mode contains(in, in) is semidet.

        % `member(Set, X)' is true iff `X' is a member of `Set'.
	% Takes O(rep_size(Set)) time.
:- pred member(T, sparse_bitset(T)) <= enum(T).
:- mode member(in, in) is semidet.
:- mode member(out, in) is nondet.

	% `insert(Set, X)' returns the union
	% of `Set' and the set containing only `X'.
	% Takes O(rep_size(Set)) time and space.
:- func insert(sparse_bitset(T), T) = sparse_bitset(T) <= enum(T).

:- pred insert(sparse_bitset(T), T, sparse_bitset(T)) <= enum(T).
:- mode insert(in, in, out) is det.

	% `insert_list(Set, X)' returns the union of `Set' and the set
	% containing only the members of `X'.
	% Same as `union(Set, list_to_set(X))', but may be more efficient.
:- func insert_list(sparse_bitset(T), list(T)) = sparse_bitset(T) <= enum(T).

:- pred insert_list(sparse_bitset(T), list(T), sparse_bitset(T)) <= enum(T).
:- mode insert_list(in, in, out) is det.

	% `delete(Set, X)' returns the difference
	% of `Set' and the set containing only `X'.
	% Takes O(rep_size(Set)) time and space.
:- func delete(sparse_bitset(T), T) = sparse_bitset(T) <= enum(T).

:- pred delete(sparse_bitset(T), T, sparse_bitset(T)) <= enum(T).
:- mode delete(in, in, out) is det.

	% `delete_list(Set, X)' returns the difference of `Set' and the set
	% containing only the members of `X'.
	% Same as `difference(Set, list_to_set(X))', but may be more efficient.
:- func delete_list(sparse_bitset(T), list(T)) = sparse_bitset(T) <= enum(T).

:- pred delete_list(sparse_bitset(T), list(T), sparse_bitset(T)) <= enum(T).
:- mode delete_list(in, in, out) is det.

	% `remove(Set, X)' returns the difference
	% of `Set' and the set containing only `X',
	% failing if `Set' does not contain `X'.
	% Takes O(rep_size(Set)) time and space.
:- func remove(sparse_bitset(T), T) = sparse_bitset(T) <= enum(T).
:- mode remove(in, in) = out is semidet.

:- pred remove(sparse_bitset(T), T, sparse_bitset(T)) <= enum(T).
:- mode remove(in, in, out) is semidet.

	% `remove_list(Set, X)' returns the difference of `Set'
	% and the set containing all the elements of `X',
	% failing if any element of `X' is not in `Set0'.
	% Same as
	%	`subset(list_to_set(X), Set), difference(Set, list_to_set(X))',
	% but may be more efficient.
:- func remove_list(sparse_bitset(T), list(T)) = sparse_bitset(T) <= enum(T).
:- mode remove_list(in, in) = out is semidet.

:- pred remove_list(sparse_bitset(T), list(T), sparse_bitset(T)) <= enum(T).
:- mode remove_list(in, in, out) is semidet.

	% `remove_least(Set0, X, Set)' is true iff `X' is the
	% least element in `Set0', and `Set' is the set which
	% contains all the elements of `Set0' except `X'.
	% Takes O(1) time and space.
:- pred remove_least(sparse_bitset(T), T, sparse_bitset(T)) <= enum(T).
:- mode remove_least(in, out, out) is semidet.

	% `union(SetA, SetB)' returns the union of `SetA' and `SetB'.
	% The efficiency of the union operation is not sensitive
	% to the argument ordering.
	% Takes O(rep_size(SetA) + rep_size(SetB)) time and space.
:- func union(sparse_bitset(T), sparse_bitset(T)) = sparse_bitset(T).

:- pred union(sparse_bitset(T), sparse_bitset(T), sparse_bitset(T)).
:- mode union(in, in, out) is det.

	% `intersect(SetA, SetB)' returns the intersection of
	% `SetA' and `SetB'. The efficiency of the intersection
	% operation is not sensitive to the argument ordering.
	% Takes O(rep_size(SetA) + rep_size(SetB)) time and
	% O(min(rep_size(SetA)), rep_size(SetB)) space.
:- func intersect(sparse_bitset(T), sparse_bitset(T)) = sparse_bitset(T).

:- pred intersect(sparse_bitset(T), sparse_bitset(T), sparse_bitset(T)).
:- mode intersect(in, in, out) is det.

	% `difference(SetA, SetB)' returns the set containing all the
	% elements of `SetA' except those that occur in `SetB'.
	% Takes O(rep_size(SetA) + rep_size(SetB)) time and
	% O(rep_size(SetA)) space.
:- func difference(sparse_bitset(T), sparse_bitset(T)) = sparse_bitset(T).

:- pred difference(sparse_bitset(T), sparse_bitset(T), sparse_bitset(T)).
:- mode difference(in, in, out) is det.

	% `count(Set)' returns the number of elements in `Set'.
	% Takes O(card(Set)) time.
:- func count(sparse_bitset(T)) = int <= enum(T).

	% `foldl(Func, Set, Start)' calls Func with each element
	% of `Set' (in sorted order) and an accumulator
	% (with the initial value of `Start'), and returns
	% the final value.
	% Takes O(card(Set)) time.
:- func foldl(func(T, U) = U, sparse_bitset(T), U) = U <= enum(T).

:- pred foldl(pred(T, U, U), sparse_bitset(T), U, U) <= enum(T).
:- mode foldl(pred(in, in, out) is det, in, in, out) is det.
:- mode foldl(pred(in, di, uo) is det, in, di, uo) is det.
:- mode foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode foldl(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode foldl(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
:- mode foldl(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.

	% `foldr(Func, Set, Start)' calls Func with each element
	% of `Set' (in reverse sorted order) and an accumulator
	% (with the initial value of `Start'), and returns
	% the final value.
	% Takes O(card(Set)) time.
:- func foldr(func(T, U) = U, sparse_bitset(T), U) = U <= enum(T).

:- pred foldr(pred(T, U, U), sparse_bitset(T), U, U) <= enum(T).
:- mode foldr(pred(in, in, out) is det, in, in, out) is det.
:- mode foldr(pred(in, di, uo) is det, in, di, uo) is det.
:- mode foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode foldr(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode foldr(pred(in, di, uo) is cc_multi, in, di, uo) is cc_multi.
:- mode foldr(pred(in, in, out) is cc_multi, in, in, out) is cc_multi.

%--------------------------------------------------%


Node:stack, Next:, Previous:sparse_bitset, Up:Top

53 stack


%--------------------------------------------------%
% Copyright (C) 1994-1995, 1997-1999 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: stack.m.
% Main author: fjh.
% Stability: high.

% This file contains a `stack' ADT.
% Stacks are implemented here using lists.

%--------------------------------------------------%

:- module stack.
:- interface.
:- import_module list.

:- type stack(_T).

	% `stack__init(Stack)' is true iff `Stack' is an empty stack.

:- pred stack__init(stack(_T)).
:- mode stack__init(out) is det.

:- func stack__init = stack(T).

	% `stack__is_empty(Stack)' is true iff `Stack' is an empty stack.

:- pred stack__is_empty(stack(_T)).
:- mode stack__is_empty(in) is semidet.

	% `stack__is_full(Stack)' is intended to be true iff `Stack'
	% is a stack whose capacity is exhausted.  This implementation
	% allows arbitrary-sized stacks, so stack__is_full always fails.

:- pred stack__is_full(stack(_T)).
:- mode stack__is_full(in) is semidet.

	% `stack__push(Stack0, Elem, Stack)' is true iff `Stack' is
	% the stack which results from pushing `Elem' onto the top
	% of `Stack0'.

:- pred stack__push(stack(T), T, stack(T)).
:- mode stack__push(in, in, out) is det.

:- func stack__push(stack(T), T) = stack(T).

	% `stack__push_list(Stack0, Elems, Stack)' is true iff `Stack'
	% is the stack which results from pushing the elements of the
	% list `Elems' onto the top of `Stack0'.

:- pred stack__push_list(stack(T), list(T), stack(T)).
:- mode stack__push_list(in, in, out) is det.

:- func stack__push_list(stack(T), list(T)) = stack(T).

	% `stack__top(Stack, Elem)' is true iff `Stack' is a non-empty
	% stack whose top element is `Elem'.

:- pred stack__top(stack(T), T).
:- mode stack__top(in, out) is semidet.

	% `stack__top_det' is like `stack__top' except that it will
	% call error/1 rather than failing if given an empty stack.

:- pred stack__top_det(stack(T), T).
:- mode stack__top_det(in, out) is det.

:- func stack__top_det(stack(T)) = T.

	% `stack__pop(Stack0, Elem, Stack)' is true iff `Stack0' is
	% a non-empty stack whose top element is `Elem', and `Stack'
	% the stack which results from popping `Elem' off `Stack0'.

:- pred stack__pop(stack(T), T, stack(T)).
:- mode stack__pop(in, out, out) is semidet.

	% `stack__pop_det' is like `stack__pop' except that it will
	% call error/1 rather than failing if given an empty stack.

:- pred stack__pop_det(stack(T), T, stack(T)).
:- mode stack__pop_det(in, out, out) is det.

	% `stack__depth(Stack, Depth)' is true iff `Stack' is a stack
	% containing `Depth' elements.

:- pred stack__depth(stack(_T), int).
:- mode stack__depth(in, out) is det.

:- func stack__depth(stack(T)) = int.

%--------------------------------------------------%


Node:std_util, Next:, Previous:stack, Up:Top

54 std_util


%--------------------------------------------------%
% Copyright (C) 1994-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: std_util.m.
% Main author: fjh.
% Stability: medium.

% This file is intended for all the useful standard utilities
% that don't belong elsewhere, like <stdlib.h> in C.

%--------------------------------------------------%
%--------------------------------------------------%

:- module std_util.

:- interface.

:- import_module list, set, bool.
:- import_module type_desc.

%--------------------------------------------------%

% The universal type `univ'.
% An object of type `univ' can hold the type and value of an object of any
% other type.

:- type univ.

	% type_to_univ(Object, Univ):
	% 	true iff the type stored in `Univ' is the same as the type
	%	of `Object', and the value stored in `Univ' is equal to the
	%	value of `Object'.
	%
	% Operational, the forwards mode converts an object to type `univ',
	% while the reverse mode converts the value stored in `Univ'
	% to the type of `Object', but fails if the type stored in `Univ'
	% does not match the type of `Object'.
	%
:- pred type_to_univ(T, univ).
:- mode type_to_univ(di, uo) is det.
:- mode type_to_univ(in, out) is det.
:- mode type_to_univ(out, in) is semidet.

	% univ_to_type(Univ, Object) :- type_to_univ(Object, Univ).
	%
:- pred univ_to_type(univ, T).
:- mode univ_to_type(in, out) is semidet.
:- mode univ_to_type(out, in) is det.
:- mode univ_to_type(uo, di) is det.

	% The function univ/1 provides the same
	% functionality as type_to_univ/2.

	% univ(Object) = Univ :- type_to_univ(Object, Univ).
	%
:- func univ(T) = univ.
:- mode univ(in) = out is det.
:- mode univ(di) = uo is det.
:- mode univ(out) = in is semidet.

	% det_univ_to_type(Univ, Object):
	% 	the same as the forwards mode of univ_to_type, but
	% 	abort if univ_to_type fails.
	%
:- pred det_univ_to_type(univ, T).
:- mode det_univ_to_type(in, out) is det.

	% univ_type(Univ):
	%	returns the type_desc for the type stored in `Univ'.
	%
:- func univ_type(univ) = type_desc__type_desc.

	% univ_value(Univ):
	%	returns the value of the object stored in Univ.
:- some [T] func univ_value(univ) = T.

%--------------------------------------------------%

% The "maybe" type.

:- type maybe(T) ---> no ; yes(T).
:- inst maybe(I) ---> no ; yes(I).

:- type maybe_error ---> ok ; error(string).
:- type maybe_error(T) ---> ok(T) ; error(string).
:- inst maybe_error(I) ---> ok(I) ; error(ground).

	% map_maybe(P, yes(Value0), yes(Value)) :- P(Value, Value).
	% map_maybe(_, no, no).
	%
:- pred map_maybe(pred(T, U), maybe(T), maybe(U)).
:- mode map_maybe(pred(in, out) is det, in, out) is det.
:- mode map_maybe(pred(in, out) is semidet, in, out) is semidet.
:- mode map_maybe(pred(in, out) is multi, in, out) is multi.
:- mode map_maybe(pred(in, out) is nondet, in, out) is nondet.

	% map_maybe(F, yes(Value)) = yes(F(Value)).
	% map_maybe(_, no) = no.
	%
:- func map_maybe(func(T) = U, maybe(T)) = maybe(U).

	% fold_maybe(P, yes(Value), Acc0, Acc) :- P(Value, Acc0, Acc).
	% fold_maybe(_, no, Acc, Acc).
:- pred fold_maybe(pred(T, U, U), maybe(T), U, U).
:- mode fold_maybe(pred(in, in, out) is det, in, in, out) is det.
:- mode fold_maybe(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode fold_maybe(pred(in, di, uo) is det, in, di, uo) is det.

	% fold_maybe(F, yes(Value), Acc0) = F(Acc0).
	% fold_maybe(_, no, Acc) = Acc.
:- func fold_maybe(func(T, U) = U, maybe(T), U) = U.

	% map_fold_maybe(P, yes(Value0), yes(Value), Acc0, Acc) :-
	%       P(Value, Value, Acc0, Acc).
	% map_fold_maybe(_, no, no, Acc, Acc).
	%
:- pred map_fold_maybe(pred(T, U, Acc, Acc), maybe(T), maybe(U), Acc, Acc).
:- mode map_fold_maybe(pred(in, out, in, out) is det, in, out, in, out) is det.
:- mode map_fold_maybe(pred(in, out, di, uo) is det, in, out, di, uo) is det.

	% As above, but with two accumulators.
:- pred map_fold2_maybe(pred(T, U, Acc1, Acc1, Acc2, Acc2),
	maybe(T), maybe(U), Acc1, Acc1, Acc2, Acc2).
:- mode map_fold2_maybe(pred(in, out, in, out, in, out) is det, in, out,
	in, out, in, out) is det.
:- mode map_fold2_maybe(pred(in, out, in, out, di, uo) is det,
	in, out, in, out, di, uo) is det.

%--------------------------------------------------%

% The "unit" type - stores no information at all.

:- type unit		--->	unit.

:- type unit(T)		--->	unit1.

%--------------------------------------------------%

% The "pair" type.  Useful for many purposes.

:- type pair(T1, T2)	--->	(T1 - T2).
:- type pair(T)		==	pair(T,T).
:- inst pair(I1, I2)	--->	(I1 - I2).
:- inst pair(I)		==	pair(I,I).

	% Return the first element of the pair.
:- pred fst(pair(X,Y)::in, X::out) is det.
:- func fst(pair(X,Y)) = X.

	% Return the second element of the pair.
:- pred snd(pair(X,Y)::in, Y::out) is det.
:- func snd(pair(X,Y)) = Y.

:- func pair(T1, T2) = pair(T1, T2).

%--------------------------------------------------%

% solutions/2 collects all the solutions to a predicate and
% returns them as a list in sorted order, with duplicates removed.
% solutions_set/2 returns them as a set.
% unsorted_solutions/2 returns them as an unsorted list with possible
% duplicates; since there are an infinite number of such lists,
% this must be called from a context in which only a single solution
% is required.

:- pred solutions(pred(T), list(T)).
:- mode solutions(pred(out) is multi, out(non_empty_list)) is det.
:- mode solutions(pred(out) is nondet, out) is det.

:- func solutions(pred(T)) = list(T).
:- mode solutions(pred(out) is multi) = out(non_empty_list) is det.
:- mode solutions(pred(out) is nondet) = out is det.

:- pred solutions_set(pred(T), set(T)).
:- mode solutions_set(pred(out) is multi, out) is det.
:- mode solutions_set(pred(out) is nondet, out) is det.

:- func solutions_set(pred(T)) = set(T).
:- mode solutions_set(pred(out) is multi) = out is det.
:- mode solutions_set(pred(out) is nondet) = out is det.

:- pred unsorted_solutions(pred(T), list(T)).
:- mode unsorted_solutions(pred(out) is multi, out(non_empty_list))
	is cc_multi.
:- mode unsorted_solutions(pred(out) is nondet, out) is cc_multi.

:- func aggregate(pred(T), func(T, U) = U, U) = U.
:- mode aggregate(pred(out) is multi, func(in, in) = out is det,
		in) = out is det.
:- mode aggregate(pred(out) is nondet, func(in, in) = out is det,
		in) = out is det.

%--------------------------------------------------%

	% aggregate/4 generates all the solutions to a predicate,
	% sorts them and removes duplicates, then applies an accumulator
	% predicate to each solution in turn:
	%
	% aggregate(Generator, Accumulator, Acc0, Acc) <=>
	%	solutions(Generator, Solutions),
	%	list__foldl(Accumulator, Solutions, Acc0, Acc).
	%

:- pred aggregate(pred(T), pred(T, U, U), U, U).
:- mode aggregate(pred(out) is multi, pred(in, in, out) is det,
	in, out) is det.
:- mode aggregate(pred(out) is multi, pred(in, di, uo) is det,
	di, uo) is det.
:- mode aggregate(pred(out) is nondet, pred(in, di, uo) is det,
	di, uo) is det.
:- mode aggregate(pred(out) is nondet, pred(in, in, out) is det,
	in, out) is det.

	% aggregate2/6 generates all the solutions to a predicate,
	% sorts them and removes duplicates, then applies an accumulator
	% predicate to each solution in turn:
	%
	% aggregate2(Generator, Accumulator, AccA0, AccA, AccB0, AccB) <=>
	%	solutions(Generator, Solutions),
	%	list__foldl2(Accumulator, Solutions, AccA0, AccA, AccB0, AccB).
	%

:- pred aggregate2(pred(T), pred(T, U, U, V, V), U, U, V, V).
:- mode aggregate2(pred(out) is multi, pred(in, in, out, in, out) is det,
	in, out, in, out) is det.
:- mode aggregate2(pred(out) is multi, pred(in, in, out, di, uo) is det,
	in, out, di, uo) is det.
:- mode aggregate2(pred(out) is nondet, pred(in, in, out, di, uo) is det,
	in, out, di, uo) is det.
:- mode aggregate2(pred(out) is nondet, pred(in, in, out, in, out) is det,
	in, out, in, out) is det.

	% unsorted_aggregate/4 generates all the solutions to a predicate
	% and applies an accumulator predicate to each solution in turn.
	% Declaratively, the specification is as follows:
	%
	% unsorted_aggregate(Generator, Accumulator, Acc0, Acc) <=>
	%	unsorted_solutions(Generator, Solutions),
	%	list__foldl(Accumulator, Solutions, Acc0, Acc).
	%
	% Operationally, however, unsorted_aggregate/4 will call the
	% Accumulator for each solution as it is obtained, rather than
	% first building a list of all the solutions.

:- pred unsorted_aggregate(pred(T), pred(T, U, U), U, U).
:- mode unsorted_aggregate(pred(out) is multi, pred(in, in, out) is det,
	in, out) is cc_multi.
:- mode unsorted_aggregate(pred(out) is multi, pred(in, di, uo) is det,
	di, uo) is cc_multi.
:- mode unsorted_aggregate(pred(out) is multi, pred(in, di, uo) is cc_multi,
	di, uo) is cc_multi.
:- mode unsorted_aggregate(pred(muo) is multi, pred(mdi, di, uo) is det,
	di, uo) is cc_multi.
:- mode unsorted_aggregate(pred(out) is nondet, pred(in, di, uo) is det,
	di, uo) is cc_multi.
:- mode unsorted_aggregate(pred(out) is nondet, pred(in, di, uo) is cc_multi,
	di, uo) is cc_multi.
:- mode unsorted_aggregate(pred(out) is nondet, pred(in, in, out) is det,
	in, out) is cc_multi.
:- mode unsorted_aggregate(pred(muo) is nondet, pred(mdi, di, uo) is det,
	di, uo) is cc_multi.

	% This is a generalization of unsorted_aggregate which allows the
	% iteration to stop before all solutions have been found.
	% Declaratively, the specification is as follows:
	%
	%	do_while(Generator, Filter, !Acc) -->
	%		unsorted_solutions(Generator, Solutions),
	%		do_while_2(Solutions, Filter, !Acc).
	%
	%	do_while_2([], _, !Acc).
	%	do_while_2([X | Xs], Filter, !Acc) :-
	%		Filter(X, More, !Acc),
	%		( More = yes ->
	%			do_while_2(Xs, Filter, !Acc)
	%		;
	%			true
	%		).
	%
	% Operationally, however, do_while/4 will call the Filter
	% predicate for each solution as it is obtained, rather than
	% first building a list of all the solutions.
	%
:- pred do_while(pred(T), pred(T, bool, T2, T2), T2, T2).
:- mode do_while(pred(out) is multi, pred(in, out, in, out) is det, in, out)
	is cc_multi.
:- mode do_while(pred(out) is multi, pred(in, out, di, uo) is det, di, uo)
	is cc_multi.
:- mode do_while(pred(out) is multi, pred(in, out, di, uo) is cc_multi, di, uo)
	is cc_multi.
:- mode do_while(pred(out) is nondet, pred(in, out, in, out) is det, in, out)
	is cc_multi.
:- mode do_while(pred(out) is nondet, pred(in, out, di, uo) is det, di, uo)
	is cc_multi.
:- mode do_while(pred(out) is nondet, pred(in, out, di, uo) is cc_multi, di, uo)
	is cc_multi.

%--------------------------------------------------%

	% General purpose higher-order programming constructs.

	% compose(F, G, X) = F(G(X))
	%
	% Function composition.
	% XXX It would be nice to have infix `o' or somesuch for this.
:- func compose(func(T2) = T3, func(T1) = T2, T1) = T3.

	% converse(F, X, Y) = F(Y, X)
:- func converse(func(T1, T2) = T3, T2, T1) = T3.

	% pow(F, N, X) = F^N(X)
	%
	% Function exponentiation.
:- func pow(func(T) = T, int, T) = T.

	% The identity function.
	%
:- func id(T) = T.

%--------------------------------------------------%

	% maybe_pred(Pred, X, Y) takes a closure Pred which transforms an
	% input semideterministically. If calling the closure with the input
	% X succeeds, Y is bound to `yes(Z)' where Z is the output of the
	% call, or to `no' if the call fails.
	%
:- pred maybe_pred(pred(T1, T2), T1, maybe(T2)).
:- mode maybe_pred(pred(in, out) is semidet, in, out) is det.

:- func maybe_func(func(T1) = T2, T1) = maybe(T2).
:- mode maybe_func(func(in) = out is semidet, in) = out is det.

%--------------------------------------------------%

	% isnt(Pred, X) <=> not Pred(X)
	%
	% This is useful in higher order programming, e.g.
	% 	Odds  = list__filter(odd, Xs)
	% 	Evens = list__filter(isnt(odd), Xs)
	%
:- pred isnt(pred(T), T).
:- mode isnt(pred(in) is semidet, in) is semidet.

%--------------------------------------------------%

	% `semidet_succeed' is exactly the same as `true', except that
	% the compiler thinks that it is semi-deterministic.  You can
	% use calls to `semidet_succeed' to suppress warnings about
	% determinism declarations which could be stricter.
	% Similarly, `semidet_fail' is like `fail' except that its
	% determinism is semidet rather than failure, and
	% `cc_multi_equal(X,Y)' is the same as `X=Y' except that it
	% is cc_multi rather than det.

:- pred semidet_succeed is semidet.

:- pred semidet_fail is semidet.

:- pred cc_multi_equal(T, T).
:- mode cc_multi_equal(di, uo) is cc_multi.
:- mode cc_multi_equal(in, out) is cc_multi.

%--------------------------------------------------%

	% The `type_desc' and `type_ctor_desc' types: these
	% provide access to type information.
	% A type_desc represents a type, e.g. `list(int)'.
	% A type_ctor_desc represents a type constructor, e.g. `list/1'.

:- type type_desc == type_desc__type_desc.
:- type type_ctor_desc == type_desc__type_ctor_desc.

	% Type_info and type_ctor_info are the old names for type_desc and
	% type_ctor_desc. They should not be used by new software.

:- type type_info == type_desc__type_desc.
:- type type_ctor_info == type_desc__type_ctor_desc.

	% (Note: it is not possible for the type of a variable to be an
	% unbound type variable; if there are no constraints on a type
	% variable, then the typechecker will use the type `void'.
	% `void' is a special (builtin) type that has no constructors.
	% There is no way of creating an object of type `void'.
	% `void' is not considered to be a discriminated union, so
	% get_functor/5 and construct/3 will fail if used upon a value
	% of this type.)

	% The function type_of/1 returns a representation of the type
	% of its argument.
	%
:- func type_of(T) = type_desc__type_desc.
:- mode type_of(unused) = out is det.

	% The predicate has_type/2 is basically an existentially typed
	% inverse to the function type_of/1.  It constrains the type
	% of the first argument to be the type represented by the
	% second argument.
:- some [T] pred has_type(T::unused, type_desc__type_desc::in) is det.

	% type_name(Type) returns the name of the specified type
	% (e.g. type_name(type_of([2,3])) = "list:list(int)").
	% Any equivalence types will be fully expanded.
	% Builtin types (those defined in builtin.m) will
	% not have a module qualifier.
	%
:- func type_name(type_desc__type_desc) = string.

	% type_ctor_and_args(Type, TypeCtor, TypeArgs):
	%	True iff `TypeCtor' is a representation of the top-level
	%	type constructor for `Type', and `TypeArgs' is a list
	%	of the corresponding type arguments to `TypeCtor',
	%	and `TypeCtor' is not an equivalence type.
	%
	% For example, type_ctor_and_args(type_of([2,3]), TypeCtor,
	% TypeArgs) will bind `TypeCtor' to a representation of the
	% type constructor list/1, and will bind `TypeArgs' to the list
	% `[Int]', where `Int' is a representation of the type `int'.
	%
	% Note that the requirement that `TypeCtor' not be an
	% equivalence type is fulfilled by fully expanding any
	% equivalence types.  For example, if you have a declaration
	% `:- type foo == bar.', then type_ctor_and_args/3 will always
	% return a representation of type constructor `bar/0', not `foo/0'.
	% (If you don't want them expanded, you can use the reverse mode
	% of make_type/2 instead.)
	%
:- pred type_ctor_and_args(type_desc__type_desc, type_desc__type_ctor_desc,
	list(type_desc__type_desc)).
:- mode type_ctor_and_args(in, out, out) is det.

	% type_ctor(Type) = TypeCtor :-
	%	type_ctor_and_args(Type, TypeCtor, _).
	%
:- func type_ctor(type_desc__type_desc) = type_desc__type_ctor_desc.

	% type_args(Type) = TypeArgs :-
	%	type_ctor_and_args(Type, _, TypeArgs).
	%
:- func type_args(type_desc__type_desc) = list(type_desc__type_desc).

	% type_ctor_name(TypeCtor) returns the name of specified
	% type constructor.
	% (e.g. type_ctor_name(type_ctor(type_of([2,3]))) = "list").
	%
:- func type_ctor_name(type_desc__type_ctor_desc) = string.

	% type_ctor_module_name(TypeCtor) returns the module name of specified
	% type constructor.
	% (e.g. type_ctor_module_name(type_ctor(type_of(2))) = "builtin").
	%
:- func type_ctor_module_name(type_desc__type_ctor_desc) = string.

	% type_ctor_arity(TypeCtor) returns the arity of specified
	% type constructor.
	% (e.g. type_ctor_arity(type_ctor(type_of([2,3]))) = 1).
	%
:- func type_ctor_arity(type_desc__type_ctor_desc) = int.

	% type_ctor_name_and_arity(TypeCtor, ModuleName, TypeName, Arity) :-
	%	Name = type_ctor_name(TypeCtor),
	%	ModuleName = type_ctor_module_name(TypeCtor),
	%	Arity = type_ctor_arity(TypeCtor).
	%
:- pred type_ctor_name_and_arity(type_desc__type_ctor_desc::in, string::out,
	string::out, int::out) is det.

	% make_type(TypeCtor, TypeArgs) = Type:
	%	True iff `Type' is a type constructed by applying
	%	the type constructor `TypeCtor' to the type arguments
	%	`TypeArgs'.
	%
	% Operationally, the forwards mode returns the type formed by
	% applying the specified type constructor to the specified
	% argument types, or fails if the length of TypeArgs is not the
	% same as the arity of TypeCtor.  The reverse mode returns a
	% type constructor and its argument types, given a type_desc;
	% the type constructor returned may be an equivalence type
	% (and hence this reverse mode of make_type/2 may be more useful
	% for some purposes than the type_ctor/1 function).
	%
:- func make_type(type_desc__type_ctor_desc, list(type_desc__type_desc)) =
	type_desc__type_desc.
:- mode make_type(in, in) = out is semidet.
:- mode make_type(out, out) = in is cc_multi.

	% det_make_type(TypeCtor, TypeArgs):
	%
	% Returns the type formed by applying the specified type
	% constructor to the specified argument types.  Aborts if the
	% length of `TypeArgs' is not the same as the arity of `TypeCtor'.
	%
:- func det_make_type(type_desc__type_ctor_desc, list(type_desc__type_desc)) =
	type_desc__type_desc.
:- mode det_make_type(in, in) = out is det.

%--------------------------------------------------%

	% num_functors(TypeInfo)
	%
	% Returns the number of different functors for the top-level
	% type constructor of the type specified by TypeInfo, or -1
	% if the type is not a discriminated union type.
	%
	% The functors of a discriminated union type are numbered from
	% zero to N-1, where N is the value returned by num_functors.
	% The functors are numbered in lexicographic order. If two
	% functors have the same name, the one with the lower arity
	% will have the lower number.
	%
:- func num_functors(type_desc__type_desc) = int.

	% get_functor(Type, FunctorNumber, FunctorName, Arity, ArgTypes)
	%
	% Binds FunctorName and Arity to the name and arity of functor number
	% FunctorNumber for the specified type, and binds ArgTypes to the
	% type_descs for the types of the arguments of that functor.
	% Fails if the type is not a discriminated union type, or if
	% FunctorNumber is out of range.
	%
:- pred get_functor(type_desc__type_desc::in, int::in, string::out, int::out,
	list(type_desc__type_desc)::out) is semidet.

	% get_functor(Type, FunctorNumber, FunctorName, Arity, ArgTypes,
	%	ArgNames)
	%
	% Binds FunctorName and Arity to the name and arity of functor number
	% FunctorNumber for the specified type, ArgTypes to the type_descs
	% for the types of the arguments of that functor, and ArgNames to the
	% field name of each functor argument, if any.  Fails if the type is
	% not a discriminated union type, or if FunctorNumber is out of range.
	%
:- pred get_functor(type_desc__type_desc::in, int::in, string::out, int::out,
	list(type_desc__type_desc)::out, list(maybe(string))::out) is semidet.

	% get_functor_ordinal(Type, I, Ordinal)
	%
	% Returns Ordinal, where Ordinal is the position in declaration order
	% for the specified type of the function symbol that is in position I
	% in lexicographic order. Fails if the type is not a discriminated
	% union type, or if I is out of range.
:- pred get_functor_ordinal(type_desc__type_desc::in, int::in, int::out)
	is semidet.

	% construct(TypeInfo, I, Args) = Term
	%
	% Returns a term of the type specified by TypeInfo whose functor
	% is functor number I of the type given by TypeInfo, and whose
	% arguments are given by Args.  Fails if the type is not a
	% discriminated union type, or if I is out of range, or if the
	% number of arguments supplied doesn't match the arity of the selected
	% functor, or if the types of the arguments do not match
	% the expected argument types of that functor.
	%
:- func construct(type_desc__type_desc, int, list(univ)) = univ.
:- mode construct(in, in, in) = out is semidet.

	% construct_tuple(Args) = Term
	%
	% Returns a tuple whose arguments are given by Args.
:- func construct_tuple(list(univ)) = univ.

%--------------------------------------------------%

:- type maybe_arg
	--->	some [T] arg(T)
	;	no_arg.

	% functor, argument and deconstruct and their variants take any type
	% (including univ), and return representation information for that type.
	%
	% The string representation of the functor that these predicates
	% return is:
	%
	% 	- for user defined types, the functor that is given
	% 	  in the type definition. For lists, this
	% 	  means the functors [|]/2 and []/0 are used, even if
	% 	  the list uses the [....] shorthand.
	%	- for integers, the string is a base 10 number,
	%	  positive integers have no sign.
	%	- for floats, the string is a floating point,
	%	  base 10 number, positive floating point numbers have
	%	  no sign.
	%	- for strings, the string, inside double quotation marks
	%	- for characters, the character inside single quotation marks
	%	- for predicates, the string <<predicate>>
	%	- for functions, the string <<function>>
	%	- for tuples, the string {}
	%	- for arrays, the string <<array>>
	%
	% The arity that these predicates return is:
	%
	% 	- for user defined types, the arity of the functor.
	%	- for integers, zero.
	%	- for floats, zero.
	%	- for strings, zero.
	%	- for characters, zero.
	%	- for predicates and functions, zero; we do not return the
	%	  number of arguments expected by the predicate or function.
	%	- for tuples, the number of elements in the tuple.
	%	- for arrays, the number of elements in the array.

	% functor(Data, Functor, Arity)
	%
	% Given a data item (Data), binds Functor to a string
	% representation of the functor and Arity to the arity of this
	% data item.  (Aborts if the type of Data is a type with a
	% non-canonical representation, i.e. one for which there is a
	% user-defined equality predicate.)
	%
	% Functor_cc succeeds even if the first argument is of a
	% non-canonical type.
	%
:- pred functor(T::in, string::out, int::out) is det.
:- pred functor_cc(T::in, string::out, int::out) is cc_multi.

	% arg(Data, ArgumentIndex) = Argument
	% argument(Data, ArgumentIndex) = ArgumentUniv
	%
	% Given a data item (Data) and an argument index
	% (ArgumentIndex), starting at 0 for the first argument, binds
	% Argument to that argument of the functor of the data item. If
	% the argument index is out of range -- that is, greater than or
	% equal to the arity of the functor or lower than 0 -- then
	% the call fails.  For argument/2 the argument returned has the
	% type univ, which can store any type.  For arg/2, if the
	% argument has the wrong type, then the call fails.
	% (Both abort if the type of Data is a type with a non-canonical
	% representation, i.e. one for which there is a user-defined
	% equality predicate.)
	%
	% arg_cc and argument_cc succeed even if the first argument is
	% of a non-canonical type.  They both encode the possible
	% non-existence of an argument at the requested location by using
	% a maybe type.
	%
:- func arg(T::in, int::in) = (ArgT::out) is semidet.
:- pred arg_cc(T::in, int::in, maybe_arg::out) is cc_multi.
:- func argument(T::in, int::in) = (univ::out) is semidet.
:- pred argument_cc(T::in, int::in, maybe(univ)::out) is cc_multi.

	% named_argument(Data, ArgumentName) = ArgumentUniv
	%
	% Same as argument/2, except the chosen argument is specified by giving
	% its name rather than its position. If Data has no argument with that
	% name, named_argument fails.
	%
	% named_argument_cc succeeds even if the first argument is
	% of a non-canonical type.
	%
:- func named_argument(T::in, string::in) = (univ::out) is semidet.
:- pred named_argument_cc(T::in, string::in, maybe(univ)::out) is cc_multi.

	% det_arg(Data, ArgumentIndex) = Argument
	% det_argument(Data, ArgumentIndex) = ArgumentUniv
	%
	% Same as arg/2 and argument/2 respectively, except that
	% for cases where arg/2 or argument/2 would fail,
	% det_arg/2 or det_argument/2 will abort.
	%
	% det_arg_cc and det_argument_cc succeed even if the first argument is
	% of a non-canonical type.
	%
:- func det_arg(T::in, int::in) = (ArgT::out) is det.
:- pred det_arg_cc(T::in, int::in, ArgT::out) is cc_multi.
:- func det_argument(T::in, int::in) = (univ::out) is det.
:- pred det_argument_cc(T::in, int::in, univ::out) is cc_multi.

	% det_named_argument(Data, ArgumentName) = ArgumentUniv
	%
	% Same as named_argument/2, except that for cases where
	% named_argument/2 would fail, det_named_argument/2 will abort.
	%
:- func det_named_argument(T::in, string::in) = (univ::out) is det.
:- pred det_named_argument_cc(T::in, string::in, univ::out) is cc_multi.

	% deconstruct(Data, Functor, Arity, Arguments)
	%
	% Given a data item (Data), binds Functor to a string
	% representation of the functor, Arity to the arity of this data
	% item, and Arguments to a list of arguments of the functor.
	% The arguments in the list are each of type univ.
	% (Aborts if the type of Data is a type with a non-canonical
	% representation, i.e. one for which there is a user-defined
	% equality predicate.)
	%
	% The cost of calling deconstruct depends greatly on how many arguments
	% Data has. If Data is an array, then each element of the array is
	% considered one of its arguments. Therefore calling deconstruct
	% on large arrays can take a very large amount of memory and a very
	% long time. If you call deconstruct in a situation in which you may
	% pass it a large array, you should probably use limited_deconstruct
	% instead.
	%
	% deconstruct_cc succeeds even if the first argument is
	% of a non-canonical type.
	%
:- pred deconstruct(T::in, string::out, int::out, list(univ)::out) is det.
:- pred deconstruct_cc(T::in, string::out, int::out, list(univ)::out)
	is cc_multi.

	% limited_deconstruct(Data, MaxArity, Functor, Arity, Arguments)
	%
	% limited_deconstruct works like deconstruct, but if the arity of T is
	% greater than MaxArity, limited_deconstruct fails. This is useful in
	% avoiding bad performance in cases where Data may be a large array.
	%
	% limited_deconstruct_cc succeeds even if the first argument is
	% of a non-canonical type.  limited_deconstruct_cc encodes the
	% possible failure of the predicate by using a maybe type.
	%
:- pred limited_deconstruct(T::in, int::in, string::out,
	int::out, list(univ)::out) is semidet.
:- pred limited_deconstruct_cc(T::in, int::in,
	maybe({string, int, list(univ)})::out) is cc_multi.

%--------------------------------------------------%


Node:store, Next:, Previous:std_util, Up:Top

55 store


%--------------------------------------------------%
% Copyright (C) 1994-1997, 2000-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: store.m.
% Main author: fjh.
% Stability: low.
%
% This file provides facilities for manipulating mutable stores.
% A store can be considered a mapping from abstract keys to their values.
% A store holds a set of nodes, each of which may contain a value of any
% type.
%
% Stores may be used to implement cyclic data structures such as
% circular linked lists, etc.
%
% Stores can have two different sorts of keys:
% mutable variables (mutvars) and references (refs).
% The difference between mutvars and refs is that
% mutvars can only be updated atomically,
% whereas it is possible to update individual fields of a reference
% one at a time (presuming the reference refers to a structured term).
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module store.
:- interface.
:- import_module io.

% Stores and keys are indexed by a type S of typeclass store(S) that
% is used to distinguish between different stores.  By using an
% existential type declaration for store__new (see below), we use the
% type system to ensure at compile time that you never attempt to use
% a key from one store to access a different store.

:- typeclass store(S).
:- type store(S).

:- instance store(io__state).
:- instance store(store(S)).

	% initialize a new store
:- some [S] pred store__new(store(S)::uo) is det.

%--------------------------------------------------%
%
% mutvars
%

	% generic_mutvar(T, S):
	% a mutable variable holding a value of type T in store S
:- type generic_mutvar(T, S).
:- type io_mutvar(T) == generic_mutvar(T, io__state).
:- type store_mutvar(T, S) == generic_mutvar(T, store(S)).

	% create a new mutable variable,
	% initialized with the specified value
:- pred store__new_mutvar(T::in, generic_mutvar(T, S)::out, S::di, S::uo)
	is det <= store(S).

	% copy_mutvar(OldMutvar, NewMutvar, S0, S)
	% is equivalent to the sequence
	% 	get_mutvar(OldMutvar, Value, S0, S1),
	% 	new_mutvar(NewMutvar, Value, S1, S )
:- pred store__copy_mutvar(generic_mutvar(T, S)::in, generic_mutvar(T, S)::out,
	S::di, S::uo) is det <= store(S).

	% lookup the value stored in a given mutable variable
:- pred store__get_mutvar(generic_mutvar(T, S)::in, T::out,
	S::di, S::uo) is det <= store(S).

	% replace the value stored in a given mutable variable
:- pred store__set_mutvar(generic_mutvar(T, S)::in, T::in,
	S::di, S::uo) is det <= store(S).

	% new_cyclic_mutvar(Func, Mutvar):
	% create a new mutable variable, whose value is initialized
	% with the value returned from the specified function `Func'.
	% The argument passed to the function is the mutvar itself,
	% whose value has not yet been initialized (this is safe
	% because the function does not get passed the store, so
	% it can't examine the uninitialized value).
	%
	% This predicate is useful for creating self-referential values
	% such as circular linked lists.
	% For example:
	%
	%	:- type clist(T, S) ---> node(T, mutvar(clist(T, S))).
	%
	%	:- pred init_cl(T::in, clist(T, S)::out,
	%		store(S)::di, store(S)::uo) is det.
	%
	%	init_cl(X, CList, !Store) :-
	%		store__new_cyclic_mutvar(func(CL) = node(X, CL), CList,
	%		!Store).
	%
:- pred store__new_cyclic_mutvar((func(generic_mutvar(T, S)) = T)::in,
	generic_mutvar(T, S)::out, S::di, S::uo) is det <= store(S).

%--------------------------------------------------%
%
% references
%

	% generic_ref(T, S):
	% a reference to value of type T in store S
:- type generic_ref(T, S).
:- type io_ref(T, S) == generic_ref(T, io__state).
:- type store_ref(T, S) == generic_ref(T, store(S)).

	% new_ref(Val, Ref):
	%	/* In C: Ref = malloc(...); *Ref = Val; */
	% Given a value of any type `T', insert a copy of the term
	% into the store and return a new reference to that term.
	% (This does not actually perform a copy, it just returns a view
	% of the representation of that value.
	% It does however allocate one cell to hold the reference;
	% you can use new_arg_ref to avoid that.)
:- pred store__new_ref(T::di, generic_ref(T, S)::out,
	S::di, S::uo) is det <= store(S).

	% ref_functor(Ref, Functor, Arity):
	% Given a reference to a term, return the functor and arity
	% of that term.
:- pred store__ref_functor(generic_ref(T, S)::in, string::out, int::out,
	S::di, S::uo) is det <= store(S).

	% arg_ref(Ref, ArgNum, ArgRef):
	%	/* Pseudo-C code: ArgRef = &Ref[ArgNum]; */
	% Given a reference to a term, return a reference to
	% the specified argument (field) of that term
	% (argument numbers start from zero).
	% It is an error if the argument number is out of range,
	% or if the argument reference has the wrong type.
:- pred store__arg_ref(generic_ref(T, S)::in, int::in,
	generic_ref(ArgT, S)::out, S::di, S::uo) is det <= store(S).

	% new_arg_ref(Val, ArgNum, ArgRef):
	%	/* Pseudo-C code: ArgRef = &Val[ArgNum]; */
	% Equivalent to `new_ref(Val, Ref), arg_ref(Ref, ArgNum, ArgRef)',
	% except that it is more efficient.
	% It is an error if the argument number is out of range,
	% or if the argument reference has the wrong type.
:- pred store__new_arg_ref(T::di, int::in, generic_ref(ArgT, S)::out,
	S::di, S::uo) is det <= store(S).

	% set_ref(Ref, ValueRef):
	%	/* Pseudo-C code: *Ref = *ValueRef; */
	% Given a reference to a term (Ref),
	% a reference to another term (ValueRef),
	% update the store so that the term referred to by Ref
	% is replaced with the term referenced by ValueRef.
:- pred store__set_ref(generic_ref(T, S)::in, generic_ref(T, S)::in,
	S::di, S::uo) is det <= store(S).

	% set_ref_value(Ref, Value):
	%	/* Pseudo-C code: *Ref = Value; */
	% Given a reference to a term (Ref), and a value (Value),
	% update the store so that the term referred to by Ref
	% is replaced with Value.
:- pred store__set_ref_value(generic_ref(T, S)::in, T::di,
	S::di, S::uo) is det <= store(S).

	% Given a reference to a term, return that term.
	% Note that this requires making a copy, so this pred may
	% be inefficient if used to return large terms; it
	% is most efficient with atomic terms.
	% XXX current implementation buggy (does shallow copy)
:- pred store__copy_ref_value(generic_ref(T, S)::in, T::uo,
	S::di, S::uo) is det <= store(S).

	% Same as above, but without making a copy.
	% Destroys the store.
:- pred store__extract_ref_value(S::di, generic_ref(T, S)::in, T::out)
	is det <= store(S).

%--------------------------------------------------%
%
% Nasty performance hacks
%
% WARNING: use of these procedures is dangerous!
% Use them only only as a last resort, only if performance
% is critical, and only if profiling shows that using the
% safe versions is a bottleneck.
%
% These procedures may vanish in some future version of Mercury.

	% `unsafe_arg_ref' is the same as `arg_ref',
	% and `unsafe_new_arg_ref' is the same as `new_arg_ref'
	% except that they doesn't check for errors,
	% and they don't work for `no_tag' types (types with
	% exactly one functor which has exactly one argument),
	% and they don't work for types with >4 functors.
	% If the argument number is out of range,
	% or if the argument reference has the wrong type,
	% or if the argument is a `no_tag' type,
	% then the behaviour is undefined, and probably harmful.

:- pred store__unsafe_arg_ref(generic_ref(T, S)::in, int::in,
	generic_ref(ArgT, S)::out, S::di, S::uo) is det <= store(S).

:- pred store__unsafe_new_arg_ref(T::di, int::in, generic_ref(ArgT, S)::out,
	S::di, S::uo) is det <= store(S).

%--------------------------------------------------%
%
% Interfaces retained only for backwards compatibility.
% Some of these are unsafe.  All of them are deprecated.
%

	% OBSOLETE: use `S' or `some [S] ... S' instead.
:- type some_store_type.

	% initialize a store
	% OBSOLETE: use store__new/1 instead
:- pred store__init(store(some_store_type)).
:- mode store__init(uo) is det.
:- pragma obsolete(store__init/1).

	% OBSOLETE: use store_mutvar/2 or generic_mutvar/2 instead.
:- type mutvar(T, S) == store_mutvar(T, S).

	% OBSOLETE: use store_mutvar/2 or generic_mutvar/2 instead.
:- type ref(T, S) == store_ref(T, S).

%--------------------------------------------------%
%--------------------------------------------------%


Node:string, Next:, Previous:store, Up:Top

56 string


%--------------------------------------------------%
% 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.
%--------------------------------------------------%

:- module string.

% Main authors: fjh, petdr.
% Stability: medium to high.

% This modules provides basic string handling facilities.

% Note that in the current implementation, strings are represented as in C,
% using a null character as the string terminator. Future implementations,
% however, might allow null characters in strings. Programmers should
% avoid creating strings that might contain null characters.

%--------------------------------------------------%

:- interface.
:- import_module list, char.
:- import_module deconstruct.
:- import_module ops.

	% Determine the length of a string.
	% An empty string has length zero.
:- func string__length(string) = int.
:- mode string__length(in) = uo is det.
:- pred string__length(string, int).
:- mode string__length(in, uo) is det.
:- mode string__length(ui, uo) is det.

	% Append two strings together.
:- func string__append(string, string) = string.
:- mode string__append(in, in) = uo is det.

:- pred string__append(string, string, string).
:- mode string__append(in, in, in) is semidet.	% implied
:- mode string__append(in, uo, in) is semidet.
:- mode string__append(in, in, uo) is det.
:- mode string__append(out, out, in) is multi.
% The following mode is semidet in the sense that it doesn't succeed more
% than once - but it does create a choice-point, which means it's inefficient
% and that the compiler can't deduce that it is semidet.
% Use string__remove_suffix instead.
% :- mode string__append(out, in, in) is semidet.

	% S1 ++ S2 = S :- string__append(S1, S2, S).
	%
	% Nicer syntax.
:- func string ++ string = string.
:- mode in ++ in = uo is det.

	% string__remove_suffix(String, Suffix, Prefix):
	% The same as string__append(Prefix, Suffix, String) except that
	% this is semidet whereas string__append(out, in, in) is nondet.
:- pred string__remove_suffix(string, string, string).
:- mode string__remove_suffix(in, in, out) is semidet.

	% string__prefix(String, Prefix) is true iff Prefix is a
	% prefix of String. Same as string__append(Prefix, _, String).
:- pred string__prefix(string, string).
:- mode string__prefix(in, in) is semidet.
:- mode string__prefix(in, out) is multi.

	% string__suffix(String, Suffix) is true iff Suffix is a
	% suffix of String. Same as string__append(_, Suffix, String).
:- pred string__suffix(string, string).
:- mode string__suffix(in, in) is semidet.
:- mode string__suffix(in, out) is multi.

:- func string__string(T) = string.
	% string__string(X): Returns a canonicalized string representation of
	% the value X using the standard Mercury operators.

:- func string__string(ops__table, T) = string.
	%
	% As above, but using the supplied table of operators.

:- pred string__string(deconstruct__noncanon_handling, ops__table, T, string).
:- mode string__string(in(do_not_allow), in, in, out) is det.
:- mode string__string(in(canonicalize), in, in, out) is det.
:- mode string__string(in(include_details_cc), in, in, out) is cc_multi.
:- mode string__string(in, in, in, out) is cc_multi.
%	string__string(NonCanon, OpsTable, X, String)
%
%	As above, but the caller specifies what behaviour should
%	occur for non-canonical terms (i.e. terms where multiple
%	representations may compare as equal):
%	- `do_not_allow' will throw an exception if (any subterm of)
%	   the argument is not canonical;
%	- `canonicalize' will substitute a string indicating the
%	   presence of a non-canonical subterm;
%	- `include_details_cc' will show the structure of any
%	   non-canonical subterms, but can only be called from a
%	   committed choice context.

	% string__char_to_string(Char, String).
	% Converts a character (single-character atom) to a string
	% or vice versa.
:- func string__char_to_string(char) = string.
:- mode string__char_to_string(in) = uo is det.
:- pred string__char_to_string(char, string).
:- mode string__char_to_string(in, uo) is det.
:- mode string__char_to_string(out, in) is semidet.

	% Convert an integer to a string.
:- func string__int_to_string(int) = string.
:- mode string__int_to_string(in) = uo is det.
:- pred string__int_to_string(int, string).
:- mode string__int_to_string(in, uo) is det.

	% string__int_to_base_string(Int, Base, String):
	% Convert an integer to a string in a given Base (between 2 and 36).
:- func string__int_to_base_string(int, int) = string.
:- mode string__int_to_base_string(in, in) = uo is det.
:- pred string__int_to_base_string(int, int, string).
:- mode string__int_to_base_string(in, in, uo) is det.

	% Convert an float to a string.
	% In the current implementation the resulting float will be in the
	% form that it was printed using the format string "%#.<prec>g".
	% <prec> will be in the range p to (p+2)
	% where p = floor(mantissa_digits * log2(base_radix) / log2(10)).
	% The precision chosen from this range will be such to allow a
	% successful decimal -> binary conversion of the float.
:- func string__float_to_string(float) = string.
:- mode string__float_to_string(in) = uo is det.
:- pred string__float_to_string(float, string).
:- mode string__float_to_string(in, uo) is det.

	% string__first_char(String, Char, Rest) is true iff Char is
	% the first character of String, and Rest is the remainder.
	%
	% WARNING: string__first_char makes a copy of Rest because the
	% garbage collector doesn't handle references into the middle
	% of an object, at least not the way we use it.
	% Repeated use of string__first_char to iterate
	% over a string will result in very poor performance.
	% Use string__foldl or string__to_char_list instead.
:- pred string__first_char(string, char, string).
:- mode string__first_char(in, in, in) is semidet.	% implied
:- mode string__first_char(in, uo, in) is semidet.	% implied
:- mode string__first_char(in, in, uo) is semidet.	% implied
:- mode string__first_char(in, uo, uo) is semidet.
:- mode string__first_char(uo, in, in) is det.

	% string__replace(String0, Search, Replace, String):
	% string__replace replaces the first occurence of Search in String0
	% with Replace to give String. It fails if Search does not occur
	% in String0.
:- pred string__replace(string, string, string, string).
:- mode string__replace(in, in, in, uo) is semidet.

	% string__replace_all(String0, Search, Replace, String):
	% string__replace_all replaces any occurences of Search in
	% String0 with Replace to give String.
:- func string__replace_all(string, string, string) = string.
:- mode string__replace_all(in, in, in) = uo is det.
:- pred string__replace_all(string, string, string, string).
:- mode string__replace_all(in, in, in, uo) is det.

	% Converts a string to lowercase.
:- func string__to_lower(string) = string.
:- mode string__to_lower(in) = uo is det.
:- pred string__to_lower(string, string).
:- mode string__to_lower(in, uo) is det.
:- mode string__to_lower(in, in) is semidet.		% implied

	% Converts a string to uppercase.
:- func string__to_upper(string) = string.
:- mode string__to_upper(in) = uo is det.
:- pred string__to_upper(string, string).
:- mode string__to_upper(in, uo) is det.
:- mode string__to_upper(in, in) is semidet.		% implied

	% Convert the first character (if any) of a string to uppercase.
:- func string__capitalize_first(string) = string.
:- pred string__capitalize_first(string::in, string::out) is det.

	% Convert the first character (if any) of a string to lowercase.
:- func string__uncapitalize_first(string) = string.
:- pred string__uncapitalize_first(string::in, string::out) is det.

	% Convert the string to a list of characters.
:- func string__to_char_list(string) = list(char).
:- pred string__to_char_list(string, list(char)).
:- mode string__to_char_list(in, out) is det.
:- mode string__to_char_list(uo, in) is det.

	% Convert a list of characters to a string.
:- func string__from_char_list(list(char)) = string.
:- mode string__from_char_list(in) = uo is det.
:- pred string__from_char_list(list(char), string).
:- mode string__from_char_list(in, uo) is det.
:- mode string__from_char_list(out, in) is det.

	% Same as string__from_char_list, except that it reverses the order
	% of the characters.
:- func string__from_rev_char_list(list(char)) = string.
:- mode string__from_rev_char_list(in) = uo is det.
:- pred string__from_rev_char_list(list(char), string).
:- mode string__from_rev_char_list(in, uo) is det.

	% Converts a signed base 10 string to an int; throws an exception
	% if the string argument does not match the regexp [+-]?[0-9]+
:- func string__det_to_int(string) = int.

	% Convert a string to an int. The string must contain only digits,
	% optionally preceded by a plus or minus sign. If the string does
	% not match this syntax, string__to_int fails.
:- pred string__to_int(string::in, int::out) is semidet.

	% Convert a string in the specified base (2-36) to an int. The
	% string must contain only digits in the specified base, optionally
	% preceded by a plus or minus sign. For bases > 10, digits 10 to 35
	% are repesented by the letters A-Z or a-z. If the string does not
	% match this syntax, the predicate fails.
:- pred string__base_string_to_int(int::in, string::in, int::out) is semidet.

	% Converts a signed base N string to an int; throws an exception
	% if the string argument is not precisely an optional sign followed
	% by a non-empty string of base N digits.
:- func string__det_base_string_to_int(int, string) = int.

	% Convert a string to an float. If the string is not a syntactically
	% correct float literal, string__to_float fails.
:- pred string__to_float(string::in, float::out) is semidet.

	% True if string contains only alphabetic characters (letters).
:- pred string__is_alpha(string::in) is semidet.

	% True if string contains only alphabetic characters and underscores.
:- pred string__is_alpha_or_underscore(string::in) is semidet.

	% True if string contains only letters, digits, and underscores.
:- pred string__is_alnum_or_underscore(string::in) is semidet.

	% string__pad_left(String0, PadChar, Width, String):
	% Insert `PadChar's at the left of `String0' until it is at least
	% as long as `Width', giving `String'.
:- func string__pad_left(string, char, int) = string.
:- pred string__pad_left(string::in, char::in, int::in, string::out) is det.

	% string__pad_right(String0, PadChar, Width, String):
	% Insert `PadChar's at the right of `String0' until it is at least
	% as long as `Width', giving `String'.
:- func string__pad_right(string, char, int) = string.
:- pred string__pad_right(string::in, char::in, int::in, string::out) is det.

	% string__duplicate_char(Char, Count, String):
	% Construct a string consisting of `Count' occurrences of `Char'
	% in sequence.
:- func string__duplicate_char(char::in, int::in) = (string::uo) is det.
:- pred string__duplicate_char(char::in, int::in, string::uo) is det.

	% string__contains_char(String, Char):
	% Succeed if `Char' occurs in `String'.
:- pred string__contains_char(string::in, char::in) is semidet.

	% string__index(String, Index, Char):
	% `Char' is the (`Index' + 1)-th character of `String'.
	% Fails if `Index' is out of range (negative, or greater than or
	% equal to the length of `String').
:- pred string__index(string::in, int::in, char::uo) is semidet.

	% string__index_det(String, Index, Char):
	% `Char' is the (`Index' + 1)-th character of `String'.
	% Calls error/1 if `Index' is out of range (negative, or greater than
	% or equal to the length of `String').
:- func string__index_det(string, int) = char.
:- pred string__index_det(string::in, int::in, char::uo) is det.

	% A synonym for index_det/2:
	% String ^ elem(Index) = string__index_det(String, Index).
:- func string ^ elem(int) = char.

	% string__unsafe_index(String, Index, Char):
	% `Char' is the (`Index' + 1)-th character of `String'.
	% WARNING: behavior is UNDEFINED if `Index' is out of range
	% (negative, or greater than or equal to the length of `String').
	% This version is constant time, whereas string__index_det
	% may be linear in the length of the string.
	% Use with care!
:- func string__unsafe_index(string, int) = char.
:- pred string__unsafe_index(string::in, int::in, char::uo) is det.

	% A synonym for unsafe_index/2:
	% String ^ unsafe_elem(Index) = string__unsafe_index(String, Index).
:- func string ^ unsafe_elem(int) = char.

	% string__chomp(String):
	% `String' minus any single trailing newline character.
:- func string__chomp(string) = string.

	% string__lstrip(String):
	% `String' minus any initial whitespace characters.
:- func string__lstrip(string) = string.

	% string__rstrip(String):
	% `String' minus any trailing whitespace characters.
:- func string__rstrip(string) = string.

	% string__strip(String):
	% `String' minus any initial and trailing whitespace characters.
:- func string__strip(string) = string.

	% string__lstrip(Pred, String):
	% `String' minus the maximal prefix consisting entirely of
	% chars satisfying `Pred'.
:- func string__lstrip(pred(char)::in(pred(in) is semidet), string::in)
	= (string::out) is det.

	% string__rstrip(Pred, String):
	% `String' minus the maximal suffix consisting entirely of
	% chars satisfying `Pred'.
:- func string__rstrip(pred(char)::in(pred(in) is semidet), string::in)
	= (string::out) is det.

	% string__prefix_length(Pred, String):
	% The length of the maximal prefix of `String' consisting entirely of
	% chars satisfying Pred.
:- func string__prefix_length(pred(char)::in(pred(in) is semidet), string::in)
	= (int::out) is det.

	% string__suffix_length(Pred, String):
	% The length of the maximal suffix of `String' consisting entirely of
	% chars satisfying Pred.
:- func suffix_length(pred(char)::in(pred(in) is semidet), string::in)
	= (int::out) is det.

	% string__set_char(Char, Index, String0, String):
	% `String' is `String0' with the (`Index' + 1)-th character
	% set to `Char'.
	% Fails if `Index' is out of range (negative, or greater than or
	% equal to the length of `String0').
:- pred string__set_char(char, int, string, string).
:- mode string__set_char(in, in, in, out) is semidet.
% XXX This mode is disabled because the compiler puts constant
% strings into static data even when they might be updated.
%:- mode string__set_char(in, in, di, uo) is semidet.

	% string__set_char_det(Char, Index, String0, String):
	% `String' is `String0' with the (`Index' + 1)-th character
	% set to `Char'.
	% Calls error/1 if `Index' is out of range (negative, or greater than
	% or equal to the length of `String0').
:- func string__set_char_det(char, int, string) = string.
:- pred string__set_char_det(char, int, string, string).
:- mode string__set_char_det(in, in, in, out) is det.
% XXX This mode is disabled because the compiler puts constant
% strings into static data even when they might be updated.
%:- mode string__set_char_det(in, in, di, uo) is det.

	% string__unsafe_set_char(Char, Index, String0, String):
	% `String' is `String0' with the (`Index' + 1)-th character
	% set to `Char'.
	% WARNING: behavior is UNDEFINED if `Index' is out of range
	% (negative, or greater than or equal to the length of `String0').
	% This version is constant time, whereas string__set_char_det
	% may be linear in the length of the string.
	% Use with care!
:- func string__unsafe_set_char(char, int, string) = string.
:- mode string__unsafe_set_char(in, in, in) = out is det.
% XXX This mode is disabled because the compiler puts constant
% strings into static data even when they might be updated.
%:- mode string__unsafe_set_char(in, in, di) = uo is det.
:- pred string__unsafe_set_char(char, int, string, string).
:- mode string__unsafe_set_char(in, in, in, out) is det.
% XXX This mode is disabled because the compiler puts constant
% strings into static data even when they might be updated.
%:- mode string__unsafe_set_char(in, in, di, uo) is det.

	% string__foldl(Closure, String, Acc0, Acc):
	% `Closure' is an accumulator predicate which is to be called for each
	% character of the string `String' in turn. The initial value of the
	% accumulator is `Acc0' and the final value is `Acc'.
	% (string__foldl is equivalent to
	% 	string__to_char_list(String, Chars),
	% 	list__foldl(Closure, Chars, Acc0, Acc)
	% but is implemented more efficiently.)
:- func string__foldl(func(char, T) = T, string, T) = T.
:- pred string__foldl(pred(char, T, T), string, T, T).
:- mode string__foldl(pred(in, in, out) is det, in, in, out) is det.
:- mode string__foldl(pred(in, di, uo) is det, in, di, uo) is det.
:- mode string__foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode string__foldl(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode string__foldl(pred(in, in, out) is multi, in, in, out) is multi.

	% string__foldl_substring(Closure, String, Start, Count, !Acc)
	% is equivalent to string__foldl(Closure, SubString, !Acc)
	% where SubString = string__substring(String, Start, Count).
:- func string__foldl_substring(func(char, T) = T, string, int, int, T) = T.
:- pred string__foldl_substring(pred(char, T, T), string, int, int, T, T).
:- mode string__foldl_substring(pred(in, in, out) is det, in, in, in,
	in, out) is det.
:- mode string__foldl_substring(pred(in, di, uo) is det, in, in, in,
	di, uo) is det.
:- mode string__foldl_substring(pred(in, in, out) is semidet, in, in, in,
	in, out) is semidet.
:- mode string__foldl_substring(pred(in, in, out) is nondet, in, in, in,
	in, out) is nondet.
:- mode string__foldl_substring(pred(in, in, out) is multi, in, in, in,
	in, out) is multi.

	% string__foldr(Closure, String, !Acc):
	% As string__foldl/4, except that processing proceeds right-to-left.
:- func string__foldr(func(char, T) = T, string, T) = T.
:- pred string__foldr(pred(char, T, T), string, T, T).
:- mode string__foldr(pred(in, in, out) is det, in, in, out) is det.
:- mode string__foldr(pred(in, di, uo) is det, in, di, uo) is det.
:- mode string__foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode string__foldr(pred(in, in, out) is nondet, in, in, out) is nondet.
:- mode string__foldr(pred(in, in, out) is multi, in, in, out) is multi.

	% string__foldr_substring(Closure, String, Start, Count, !Acc)
	% is equivalent to string__foldr(Closure, SubString, !Acc)
	% where SubString = string__substring(String, Start, Count).
:- func string__foldr_substring(func(char, T) = T, string, int, int, T) = T.
:- pred string__foldr_substring(pred(char, T, T), string, int, int, T, T).
:- mode string__foldr_substring(pred(in, in, out) is det, in, in, in,
	in, out) is det.
:- mode string__foldr_substring(pred(in, di, uo) is det, in, in, in,
	di, uo) is det.
:- mode string__foldr_substring(pred(in, in, out) is semidet, in, in, in,
	in, out) is semidet.
:- mode string__foldr_substring(pred(in, in, out) is nondet, in, in, in,
	in, out) is nondet.
:- mode string__foldr_substring(pred(in, in, out) is multi, in, in, in,
	in, out) is multi.

	% string__words(SepP, String) returns the list of non-empty substrings
	% of String (in first to last order) that are delimited by non-empty
	% sequences of chars matched by SepP. For example,
	%
	% string__words(char__is_whitespace, " the cat  sat on the  mat") =
	% 	["the", "cat", "sat", "on", "the", "mat"]
:- func string__words(pred(char), string) = list(string).
:- mode string__words(pred(in) is semidet, in) = out is det.

	% string__words(String) = string__words(char__is_whitespace, String).
:- func string__words(string) = list(string).

	% string__split(String, Count, LeftSubstring, RightSubstring):
	% `LeftSubstring' is the left-most `Count' characters of `String',
	% and `RightSubstring' is the remainder of `String'.
	% (If `Count' is out of the range [0, length of `String'], it is
	% treated as if it were the nearest end-point of that range.)
:- pred string__split(string, int, string, string).
:- mode string__split(in, in, uo, uo) is det.

	% string__left(String, Count, LeftSubstring):
	% `LeftSubstring' is the left-most `Count' characters of `String'.
	% (If `Count' is out of the range [0, length of `String'], it is
	% treated as if it were the nearest end-point of that range.)
:- func string__left(string, int) = string.
:- mode string__left(in, in) = uo is det.
:- pred string__left(string, int, string).
:- mode string__left(in, in, uo) is det.

	% string__right(String, Count, RightSubstring):
	% `RightSubstring' is the right-most `Count' characters of `String'.
	% (If `Count' is out of the range [0, length of `String'], it is
	% treated as if it were the nearest end-point of that range.)
:- func string__right(string, int) = string.
:- mode string__right(in, in) = uo is det.
:- pred string__right(string, int, string).
:- mode string__right(in, in, uo) is det.

	% string__substring(String, Start, Count, Substring):
	% `Substring' is first the `Count' characters in what would
	% remain of `String' after the first `Start' characters were
	% removed.
	% (If `Start' is out of the range [0, length of `String'], it is
	% treated as if it were the nearest end-point of that range.
	% If `Count' is out of the range [0, length of `String' - `Start'],
	% it is treated as if it were the nearest end-point of that range.)
:- func string__substring(string, int, int) = string.
:- mode string__substring(in, in, in) = uo is det.
:- pred string__substring(string, int, int, string).
:- mode string__substring(in, in, in, uo) is det.

	% string__unsafe_substring(String, Start, Count, Substring):
	% `Substring' is first the `Count' characters in what would
	% remain of `String' after the first `Start' characters were
	% removed.
	% WARNING: if `Start' is out of the range [0, length of `String'],
	% or if `Count' is out of the range [0, length of `String' - `Start'],
	% then the behaviour is UNDEFINED.
	% Use with care!
	% This version takes time proportional to the length of the
	% substring, whereas string__substring may take time proportional
	% to the length of the whole string.
:- func string__unsafe_substring(string, int, int) = string.
:- mode string__unsafe_substring(in, in, in) = uo is det.
:- pred string__unsafe_substring(string, int, int, string).
:- mode string__unsafe_substring(in, in, in, uo) is det.

	% Append a list of strings together.
:- func string__append_list(list(string)::in) = (string::uo) is det.
:- pred string__append_list(list(string), string).
:- mode string__append_list(in, uo) is det.

	% string__join_list(Separator, Strings) = JoinedString:
	% Appends together the strings in Strings, putting Separator between
	% adjacent strings. If Strings is the empty list, returns the empty
	% string.
:- func string__join_list(string::in, list(string)::in) = (string::uo) is det.

	% Compute a hash value for a string.
:- func string__hash(string) = int.
:- pred string__hash(string, int).
:- mode string__hash(in, out) is det.

	% string__sub_string_search(String, SubString, Index).
	% `Index' is the position in `String' where the first occurrence of
	% `SubString' begins. Indices start at zero, so if `SubString'
	% is a prefix of `String', this will return Index = 0.
:- pred string__sub_string_search(string, string, int).
:- mode string__sub_string_search(in, in, out) is semidet.

	% A function similar to sprintf() in C.
	%
	% For example,
	% 	string__format("%s %i %c %f\n",
	% 		[s("Square-root of"), i(2), c('='), f(1.41)], String)
	% will return
	% 	String = "Square-root of 2 = 1.41\n".
	%
	% The following options available in C are supported: flags [0+-# ],
	% a field width (or *), and a precision (could be a ".*").
	%
	% Valid conversion character types are {dioxXucsfeEgGp%}. %n is not
	% supported. string__format will not return the length of the string.
	%
	% conv	var	output form.		effect of '#'.
	% char.	type.
	%
	% d	int	signed integer
	% i	int	signed integer
	% o	int	signed octal		with '0' prefix
	% x,X	int	signed hex		with '0x', '0X' prefix
	% u	int	unsigned integer
	% c	char	character
	% s	string	string
	% f	float	rational number		with '.', if precision 0
	% e,E	float	[-]m.dddddE+-xx		with '.', if precision 0
	% g,G	float	either e or f		with trailing zeros.
	% p	int	integer
	%
	% An option of zero will cause any padding to be zeros rather than
	% spaces. A '-' will cause the output to be left-justified in its
	% 'space'. (With a `-', the default is for fields to be
	% right-justified.)
	% A '+' forces a sign to be printed. This is not sensible for string
	% and character output. A ' ' causes a space to be printed before a
	% thing if there is no sign there. The other option is the '#', which
	% modifies the output string's format. These options are normally put
	% directly after the '%'.
	%
	% Note:
	% 	%#.0e, %#.0E now prints a '.' before the 'e'.
	%
	% 	Asking for more precision than a float actually has will
	% 	result in potentially misleading output.
	%
	% 	Numbers are now rounded by precision value, not
	% 	truncated as previously.
	%
	% 	The implementation uses the sprintf() function, so the
	% 	actual output will depend on the C standard library.
	%
:- func string__format(string, list(string__poly_type)) = string.
:- pred string__format(string, list(string__poly_type), string).
:- mode string__format(in, in, out) is det.

%--------------------------------------------------%

:- type string__poly_type
	--->	f(float)
	;	i(int)
	;	s(string)
	;	c(char).

%--------------------------------------------------%


Node:term, Next:, Previous:string, Up:Top

57 term


%--------------------------------------------------%
% Copyright (C) 1993-2000, 2003-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: term.m.
% Main author: fjh.
% Stability: medium.

% This file provides a type `term' used to represent Prolog terms,
% and various predicates to manipulate terms and substitutions.
% Terms are polymorphic so that terms representing different kinds of
% thing can be made to be of different types so they don't get mixed up.

%--------------------------------------------------%

:- module term.
:- interface.
:- import_module enum, list, map, std_util.

%--------------------------------------------------%

:- type term(T)
	--->	term__functor(
			const,
			list(term(T)),
			term__context
		)
	;	term__variable(
			var(T)
		).

:- type const
	--->	term__atom(string)
	;	term__integer(int)
	;	term__string(string)
	;	term__float(float).

:- type term__context
	--->    term__context(string, int).
				% file name, line number.

:- type var(T).
:- type var_supply(T).

:- type generic
	--->	generic.

:- type term	==	term(generic).
:- type var	==	var(generic).

%--------------------------------------------------%

	% The following predicates can convert values of (almost)
	% any type to the type `term' and back again.

:- type term_to_type_result(T, U)
	--->	ok(T)
	;	error(term_to_type_error(U)).

:- type term_to_type_result(T) == term_to_type_result(T, generic).

	% term__try_term_to_type(Term, Result):
	% Try to convert the given term to a ground value of type T.
	% If successful, return `ok(X)' where X is the converted value.
	% If Term is not ground, return `mode_error(Var, Context)',
	% where Var is a variable occurring in Term.
	% If Term is not a valid term of the specified type, return
	% `type_error(SubTerm, ExpectedType, Context, ArgContexts)',
	% where SubTerm is a sub-term of Term and ExpectedType is
	% the type expected for that part of Term.
	% Context specifies the file and line number where the
	% offending part of the term was read in from, if available.
	% ArgContexts specifies the path from the root of the term
	% to the offending subterm.
:- func term__try_term_to_type(term(U)) = term_to_type_result(T, U).
:- pred term__try_term_to_type(term(U)::in, term_to_type_result(T, U)::out)
	is det.

:- type term_to_type_error(T)
	--->	type_error(
			term(T),
			type_desc,
			term__context,
			term_to_type_context
		)
	;	mode_error(
			var(T),
			term_to_type_context
		).

:- type term_to_type_context == list(term_to_type_arg_context).

:- type term_to_type_arg_context
	--->	arg_context(
			const,		% functor
			int,		% argument number (starting from 1)
			term__context	% filename & line number
		).

	% term_to_type(Term, Type) :- try_term_to_type(Term, ok(Type)).
:- pred term__term_to_type(term(U)::in, T::out) is semidet.

	% like term_to_type, but calls error/1 rather than failing.
:- func term__det_term_to_type(term(_)) = T.
:- pred term__det_term_to_type(term(_)::in, T::out) is det.

	% converts a value to a term representation of that value
:- func term__type_to_term(T) = term(_).
:- pred term__type_to_term(T::in, term(_)::out) is det.

	% calls term__type_to_term on the value stored in the univ
	% (as distinct from the univ itself).
:- func term__univ_to_term(univ) = term(_).
:- pred term__univ_to_term(univ::in, term(_)::out) is det.

%--------------------------------------------------%

	% term__vars(Term, Vars)
	% Vars is the list of variables contained in Term, in the order
	% obtained by traversing the term depth first, left-to-right.
:- func term__vars(term(T)) = list(var(T)).
:- pred term__vars(term(T)::in, list(var(T))::out) is det.

	% As above, but with an accumulator.
:- func term__vars_2(term(T), list(var(T))) = list(var(T)).
:- pred term__vars_2(term(T)::in, list(var(T))::in, list(var(T))::out) is det.

	% term__vars_list(TermList, Vars)
	% Vars is the list of variables contained in TermList, in the order
	% obtained by traversing the list of terms depth-first, left-to-right.
:- func term__vars_list(list(term(T))) = list(var(T)).
:- pred term__vars_list(list(term(T))::in, list(var(T))::out) is det.

	% term__contains_var(Term, Var)
	% True if Term contains Var. On backtracking returns all the
	% variables contained in Term.
:- pred term__contains_var(term(T), var(T)).
:- mode term__contains_var(in, in) is semidet.
:- mode term__contains_var(in, out) is nondet.

	% term__contains_var_list(TermList, Var)
	% True if TermList contains Var. On backtracking returns all the
	% variables contained in Term.
:- pred term__contains_var_list(list(term(T)), var(T)).
:- mode term__contains_var_list(in, in) is semidet.
:- mode term__contains_var_list(in, out) is nondet.

:- type substitution(T) == map(var(T), term(T)).
:- type substitution	== substitution(generic).

	% term__unify(Term1, Term2, Bindings0, Bindings):
	% Unify (with occur check) two terms with respect to a set of bindings
	% and possibly update the set of bindings.
:- pred term__unify(term(T)::in, term(T)::in, substitution(T)::in,
	substitution(T)::out) is semidet.

	% term__substitute(Term0, Var, Replacement, Term):
	% Replace all occurrences of Var in Term0 with Replacement,
	% and return the result in Term.
:- func term__substitute(term(T), var(T), term(T)) = term(T).
:- pred term__substitute(term(T)::in, var(T)::in, term(T)::in, term(T)::out)
	is det.

	% As above, except for a list of terms rather than a single term.
:- func term__substitute_list(list(term(T)), var(T), term(T)) = list(term(T)).
:- pred term__substitute_list(list(term(T))::in, var(T)::in, term(T)::in,
	list(term(T))::out) is det.

	% term__substitute_corresponding(Vars, Repls, Term0, Term).
	% Replace all occurrences of variables in Vars with the corresponding
	% term in Repls, and return the result in Term. If Vars contains
	% duplicates, or if Vars is not the same length as Repls, the
	% behaviour is undefined and probably harmful.
:- func term__substitute_corresponding(list(var(T)), list(term(T)),
	term(T)) = term(T).
:- pred term__substitute_corresponding(list(var(T))::in, list(term(T))::in,
	term(T)::in, term(T)::out) is det.

	% As above, except applies to a list of terms rather than a
	% single term.
:- func term__substitute_corresponding_list(list(var(T)),
	list(term(T)), list(term(T))) = list(term(T)).
:- pred term__substitute_corresponding_list(list(var(T))::in,
	list(term(T))::in, list(term(T))::in, list(term(T))::out) is det.

	% term__apply_rec_substitution(Term0, Substitution, Term):
	% Recursively apply substitution to Term0 until no more substitions
	% can be applied, and then return the result in Term.
:- func term__apply_rec_substitution(term(T), substitution(T)) = term(T).
:- pred term__apply_rec_substitution(term(T)::in, substitution(T)::in,
	term(T)::out) is det.

	% As above, except applies to a list of terms rather than a
	% single term.
:- func term__apply_rec_substitution_to_list(list(term(T)),
	substitution(T)) = list(term(T)).
:- pred term__apply_rec_substitution_to_list(list(term(T))::in,
	substitution(T)::in, list(term(T))::out) is det.

	% term__apply_substitution(Term0, Substitution, Term):
	% Apply substitution to Term0 and return the result in Term.
:- func term__apply_substitution(term(T), substitution(T)) = term(T).
:- pred term__apply_substitution(term(T)::in, substitution(T)::in,
	term(T)::out) is det.

	% As above, except applies to a list of terms rather than a
	% single term.
:- func term__apply_substitution_to_list(list(term(T)),
	substitution(T)) = list(term(T)).
:- pred term__apply_substitution_to_list(list(term(T))::in,
	substitution(T)::in, list(term(T))::out) is det.

	% term__occurs(Term0, Var, Substitution):
	% True iff Var occurs in the term resulting after applying
	% Substitution to Term0.
:- pred term__occurs(term(T)::in, var(T)::in, substitution(T)::in) is semidet.

	% As above, except for a list of terms rather than a single term.
:- pred term__occurs_list(list(term(T))::in, var(T)::in, substitution(T)::in)
	is semidet.

	% term__relabel_variable(Term0, OldVar, NewVar, Term):
	% Replace all occurences of OldVar in Term0 with NewVar and
	% put the result in Term.
:- func term__relabel_variable(term(T), var(T), var(T)) = term(T).
:- pred term__relabel_variable(term(T)::in, var(T)::in, var(T)::in,
	term(T)::out) is det.

	% As above, except applies to a list of terms rather than a
	% single term.
	% XXX the name of the predicate is misleading.
:- func term__relabel_variables(list(term(T)), var(T), var(T)) = list(term(T)).
:- pred term__relabel_variables(list(term(T))::in, var(T)::in, var(T)::in,
	list(term(T))::out) is det.

	% Same as term__relabel_variable, except relabels multiple variables.
	% If a variable is not in the map, it is not replaced.
:- func term__apply_variable_renaming(term(T), map(var(T), var(T))) = term(T).
:- pred term__apply_variable_renaming(term(T)::in, map(var(T), var(T))::in,
	term(T)::out) is det.

	% Applies term__apply_variable_renaming to a list of terms.
:- func term__apply_variable_renaming_to_list(list(term(T)),
	map(var(T), var(T))) = list(term(T)).
:- pred term__apply_variable_renaming_to_list(list(term(T))::in,
	map(var(T), var(T))::in, list(term(T))::out) is det.

	% term__is_ground(Term, Bindings) is true iff no variables contained
	% in Term are non-ground in Bindings.
:- pred term__is_ground(term(T)::in, substitution(T)::in) is semidet.

	% term__is_ground(Term) is true iff Term contains no variables.
:- pred term__is_ground(term(T)::in) is semidet.

%--------------------------------------------------%

	% To manage a supply of variables, use the following 2 predicates.
	% (We might want to give these a unique mode later.)

	% term__init_var_supply(VarSupply):
	% Returns a fresh var_supply for producing fresh variables.
:- func term__init_var_supply = var_supply(T).
:- pred term__init_var_supply(var_supply(T)).
:- mode term__init_var_supply(out) is det.
:- mode term__init_var_supply(in) is semidet. % implied

	% term__create_var(VarSupply0, Variable, VarSupply):
	% Create a fresh variable (var) and return the updated var_supply.
:- pred term__create_var(var_supply(T), var(T), var_supply(T)).
:- mode term__create_var(in, out, out) is det.

	% term__var_id(Variable):
	% Returns a unique number associated with this variable w.r.t.
	% its originating var_supply.
:- func term__var_id(var(T)) = int.

%--------------------------------------------------%

	% from_int/1 should only be applied to integers returned
	% by to_int/1. This instance declaration is needed to
	% allow sets of variables to be represented using
	% sparse_bitset.m.
:- instance enum(var(_)).

	% Convert a variable to an int.
	% Different variables map to different ints.
	% Other than that, the mapping is unspecified.
:- func term__var_to_int(var(T)) = int.
:- pred term__var_to_int(var(T)::in, int::out) is det.

%--------------------------------------------------%

	% Given a term context, return the source line number.
:- pred term__context_line(term__context::in, int::out) is det.
:- func term__context_line(term__context) = int.

	% Given a term context, return the source file.
:- pred term__context_file(term__context::in, string::out) is det.
:- func term__context_file(term__context) = string.

	% Used to initialize the term context when reading in
	% (or otherwise constructing) a term.
:- pred term__context_init(term__context::out) is det.
:- func term__context_init = term__context.
:- pred term__context_init(string::in, int::in, term__context::out) is det.
:- func term__context_init(string, int) = term__context.

	% Convert a list of terms which are all vars into a list
	% of vars.  Abort (call error/1) if the list contains
	% any non-variables.

:- pred term__term_list_to_var_list(list(term(T))::in, list(var(T))::out)
	is det.
:- func term__term_list_to_var_list(list(term(T))) = list(var(T)).

	% Convert a list of terms which are all vars into a list
	% of vars (or vice versa).

:- pred term__var_list_to_term_list(list(var(T)), list(term(T))).
:- mode term__var_list_to_term_list(in, out) is det.
:- mode term__var_list_to_term_list(out, in) is semidet.

:- func term__var_list_to_term_list(list(var(T))) = list(term(T)).

%--------------------------------------------------%

	% term__generic_term(Term) is true iff `Term' is a term of type
	% `term' ie `term(generic)'.
	% It is useful because in some instances it doesn't matter what
	% the type of a term is, and passing it to this predicate will
	% ground the type avoiding unbound type variable warnings.
:- pred term__generic_term(term::in) is det.

	% Coerce a term of type `T' into a term of type `U'.
:- pred term__coerce(term(T)::in, term(U)::out) is det.
:- func term__coerce(term(T)) = term(U).

	% Coerce a var of type `T' into a var of type `U'.
:- pred term__coerce_var(var(T)::in, var(U)::out) is det.
:- func term__coerce_var(var(T)) = var(U).

	% Coerce a var_supply of type `T' into a var_supply of type `U'.
:- pred term__coerce_var_supply(var_supply(T)::in, var_supply(U)::out) is det.
:- func term__coerce_var_supply(var_supply(T)) = var_supply(U).

%--------------------------------------------------%


Node:term_io, Next:, Previous:term, Up:Top

58 term_io


%--------------------------------------------------%
% Copyright (C) 1994-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: term_io.m.
% Main author: fjh.
% Stability: medium to high.
%
% This file encapsulates all the term I/O.
% This exports predicates to read and write terms in the
% nice ground representation provided in term.m.
%
%--------------------------------------------------%

:- module term_io.
:- interface.
:- import_module char, io, varset, ops, term.

% External interface: exported predicates

% The following are not yet implemented.
%
% :- type op_type ---> fx; fy; xf; yf; xfx; xfy; yfx; fxx; fxy; fyx; fyy.
%
% 	% term_io__op(Prec, Type, OpName, !IO):
% 	% Define an operator as per Prolog op/3 for future calls
% 	% to term_io__read_term.
% :- pred term_io__op(int::in, op_type::in, string::in, io::di, io::uo) is det.
%
% :- type op_details ---> op(int, op_type, string).
%
% 	% Return a list containing all the current operator definitions.
% 	% Does not modify the io__state.
% :- pred term_io__current_ops(list(op_details)::out, io::di, io::uo) is det.

:- type read_term(T) ---> eof ; error(string, int) ; term(varset(T), term(T)).

:- type read_term	== read_term(generic).

	% term_io__read_term(Result, IO0, IO1).
	% Read a term from standard input. Similar to NU-Prolog read_term/2,
	% except that resulting term is in the ground representation.
	% Binds Result to either `eof', `term(VarSet, Term)', or
	% `error(Message, LineNumber)'.
:- pred term_io__read_term(read_term(T)::out, io::di, io::uo) is det.

	% As above, except uses the given operator table instead of
	% the standard Mercury operators.
:- pred term_io__read_term_with_op_table(Ops::in, read_term(T)::out,
	io::di, io::uo) is det <= op_table(Ops).

	% Writes a term to standard output.
:- pred term_io__write_term(varset(T)::in, term(T)::in, io::di, io::uo) is det.

	% As above, except uses the given operator table instead of the
	% standard Mercury operators.
:- pred term_io__write_term_with_op_table(Ops::in, varset(T)::in, term(T)::in,
	io::di, io::uo) is det <= op_table(Ops).

	% As above, except it appends a period and new-line.
:- pred term_io__write_term_nl(varset(T)::in, term(T)::in, io::di, io::uo)
	is det.

	% As above, except it appends a period and new-line.
:- pred term_io__write_term_nl_with_op_table(Ops::in, varset(T)::in,
	term(T)::in, io::di, io::uo) is det <= op_table(Ops).

	% Writes a constant (integer, float, string, or atom) to stdout.
:- pred term_io__write_constant(const::in, io::di, io::uo) is det.

	% Like term_io__write_constant, but return the result in a string.
:- func term_io__format_constant(const) = string.

	% Writes a variable to stdout.
:- pred term_io__write_variable(var(T)::in, varset(T)::in, io::di, io::uo)
	is det.

	% As above, except uses the given operator table instead of the
	% standard Mercury operators.
:- pred term_io__write_variable_with_op_table(Ops::in, var(T)::in,
	varset(T)::in, io::di, io::uo) is det <= op_table(Ops).

	% Given a string S, write S in double-quotes, with characters
	% escaped if necessary, to stdout.
:- pred term_io__quote_string(string::in, io::di, io::uo) is det.

	% Like term_io__quote_string, but return the result in a string.
:- func term_io__quoted_string(string) = string.

	% Given an atom-name A, write A, enclosed in single-quotes if necessary,
	% with characters escaped if necessary, to stdout.
:- pred term_io__quote_atom(string::in, io::di, io::uo) is det.

	% Like term_io__quote_atom, but return the result in a string.
:- func term_io__quoted_atom(string) = string.

	% Given a character C, write C in single-quotes,
	% escaped if necessary, to stdout.
:- pred term_io__quote_char(char::in, io::di, io::uo) is det.

:- func term_io__quoted_char(char) = string.
	% Like term_io__quote_char, but return the result in a string.

	% Given a character C, write C, escaped if necessary, to stdout.
	% The character is not enclosed in quotes.
:- pred term_io__write_escaped_char(char::in, io::di, io::uo) is det.

	% Like term_io__write_escaped_char, but return the result in a string.
:- func term_io__escaped_char(char) = string.

	% Given a string S, write S, with characters escaped if necessary,
	% to stdout. The string is not enclosed in quotes.
:- pred term_io__write_escaped_string(string::in, io::di, io::uo) is det.

	% Like term_io__write_escaped_char, but return the result in a string.
:- func term_io__escaped_string(string) = string.

	% `term_io__quote_single_char' is the old (misleading) name for
	% `term_io__write_escaped_char'. Use the latter instead.
:- pragma obsolete(term_io__quote_single_char/3).
:- pred term_io__quote_single_char(char::in, io::di, io::uo) is det.

%--------------------------------------------------%


Node:time, Next:, Previous:term_io, Up:Top

59 time


%--------------------------------------------------%
% Originally written in 1999 by Tomas By <T.By@dcs.shef.ac.uk>
% "Feel free to use this code or parts of it any way you want."
%
% Some portions are Copyright (C) 1999-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: time.m.
% Main authors: Tomas By <T.By@dcs.shef.ac.uk>, fjh
% Stability: medium
%
% Time functions.
%
%--------------------------------------------------%

:- module time.

:- interface.

:- import_module io, std_util.

	% The `clock_t' type represents times measured in clock ticks.
	% NOTE: the unit used for a value of this type depends on whether it was
	% returned by `time__clock' or `time__times'.  See the comments on these
	% predicates below.
:- type clock_t == int.

	% The `tms' type holds information about the amount of processor
	% time that a process and its child processes have consumed.
:- type tms --->
	tms(
		clock_t,	% tms_utime: user time
		clock_t,	% tms_stime: system time
		clock_t,	% tms_cutime: user time of children
		clock_t		% tms_cstime: system time of children
	).

	% The `time_t' type is an abstract type that represents
	% calendar times.
:- type time_t.

	% The `tm' type is a concrete type that represents calendar
	% times, broken down into their constituent components.
	% Comparison (via compare/3) of `tm' values whose `tm_dst'
	% components are identical is equivalent to comparison of
	% the times those `tm' values represent.
:- type tm --->
	tm(
		tm_year	:: int,		% Year (number since 1900)
		tm_mon	:: int,		% Month (number since January, 0-11)
		tm_mday	:: int,		% MonthDay (1-31)
		tm_hour	:: int,		% Hours (after midnight, 0-23)
		tm_min	:: int,		% Minutes (0-59)
		tm_sec	:: int,		% Seconds (0-61)
					% (60 and 61 are for leap seconds)
		tm_yday	:: int,		% YearDay (number since Jan 1st, 0-365)
		tm_wday	:: int,		% WeekDay (number since Sunday, 0-6)
		tm_dst	:: maybe(dst)	% IsDST (is DST in effect?)
	).

:- type dst
	--->	standard_time	% no, DST is not in effect
	;	daylight_time.	% yes, DST is in effect

	% Some of the procedures in this module throw this type
	% as an exception if they can't obtain a result.
:- type time_error --->
	time_error(string).	% Error message

%--------------------------------------------------%

	% time__clock(Result, IO_state, IO_state):
	%	Returns the elapsed processor time (number of clock
	%	ticks). The base time is arbitrary but doesn't change
	%	within a single process.
	%	If the time cannot be obtained, this procedure
	%	will throw a time_error exception.
	%	To obtain a time in seconds, divide Result by
	%	`time__clocks_per_sec'.
	%
:- pred time__clock(clock_t::out, io::di, io::uo) is det.

	% time__clocks_per_sec:
	%	Returns the number of "clocks" per second as defined by
	%	CLOCKS_PER_SEC.  A `clock_t' value returned by `time__clock' can
	%	be divided by this value to obtain a time in seconds.
	%
:- func time__clocks_per_sec = int.

%--------------------------------------------------%

	% time__time(Result, IO_state, IO_state):
	%	Returns the current (simple) calendar time.
	%	If the time cannot be obtained, this procedure
	%	will throw a time_error exception.
	%
:- pred time__time(time_t::out, io::di, io::uo) is det.

%--------------------------------------------------%

	% time__times(ProcessorTime, ElapsedRealTime, IO_state, IO_state)
	%	(POSIX)
	%	Returns the processor time information in the `tms'
	%	value, and the elapsed real time relative to an
	%	arbitrary base in the `clock_t' value.
	%	To obtain a time in seconds, divide the result by
	%	`time__clk_tck'.
	%	If the time cannot be obtained, this procedure
	%	will throw a time_error exception.
	%
	%	On non-POSIX systems that do not support this functionality,
	%	this procedure may simply always throw an exception.
	%
:- pred time__times(tms::out, clock_t::out, io::di, io::uo) is det.

	% time__clk_tck:
	%	Returns the number of "clock ticks" per second as defined by
	%	sysconf(_SC_CLK_TCK).  A `clock_t' value returned by
	%	`time__times' can be divided by this value to obtain a time in
	%	seconds.
	%
	%	On non-POSIX systems that do not support this functionality,
	%	this procedure may simply always throw an exception.
	%
:- func time__clk_tck = int.

%--------------------------------------------------%

	% time__difftime(Time1, Time0) = Diff:
	%	Computes the number of seconds elapsed between
	%	`Time1' and `Time0'.
	%
:- func time__difftime(time_t, time_t) = float.

	% time__localtime(Time) = TM:
	%	Converts the calendar time `Time' to a broken-down
	%	representation, expressed relative to the user's
	%	specified time zone.
	%
:- func time__localtime(time_t) = tm.

	% time__gmtime(Time) = TM:
	%	Converts the calendar time `Time' to a broken-down
	%	representation, expressed as UTC (Universal Coordinated Time).
	%
:- func time__gmtime(time_t) = tm.

	% time__mktime(TM) = Time:
	%	Converts the broken-down local time value to calendar time.
	%	It also normalises the value by filling in day of
	%	week and day of year based on the other components.
	%
:- func time__mktime(tm) = time_t.

%--------------------------------------------------%

	% time__asctime(TM) = String:
	% 	Converts the broken-down time value `TM' to a string
	% 	in a standard format.
	%
:- func time__asctime(tm) = string.

	% time__ctime(Time) = String:
	% 	Converts the calendar time value `Time' to a string
	% 	in a standard format.
	%	(ie same as "asctime (localtime (<time>))")
	%
:- func time__ctime(time_t) = string.

%--------------------------------------------------%
%--------------------------------------------------%


Node:tree234, Next:, Previous:time, Up:Top

60 tree234


%--------------------------------------------------%
% Copyright (C) 1994-1997,1999-2000,2002-2003 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.
%--------------------------------------------------%

% tree234 - implements a map (dictionary) using 2-3-4 trees.
% main author: conway.
% stability: medium.

% See map.m for documentation.

%--------------------------------------------------%

:- module tree234.

:- interface.

:- import_module list, assoc_list.
:- import_module term.	% for var/1.

:- type tree234(K, V).

:- pred tree234__init(tree234(K, V)).
:- mode tree234__init(uo) is det.

:- func tree234__init = tree234(K, V).

:- pred tree234__is_empty(tree234(K, V)).
:- mode tree234__is_empty(in) is semidet.

:- pred tree234__member(tree234(K, V), K, V).
:- mode tree234__member(in, out, out) is nondet.

:- pred tree234__search(tree234(K, V), K, V).
:- mode tree234__search(in, in, out) is semidet.

:- pred tree234__lookup(tree234(K, V), K, V).
:- mode tree234__lookup(in, in, out) is det.

:- func tree234__lookup(tree234(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 tree234__lower_bound_search(tree234(K, V), K, K, V).
:- mode tree234__lower_bound_search(in, in, out, 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 tree234__lower_bound_lookup(tree234(K, V), K, K, V).
:- mode tree234__lower_bound_lookup(in, in, out, 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 tree234__upper_bound_search(tree234(K, V), K, K, V).
:- mode tree234__upper_bound_search(in, in, out, 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 tree234__upper_bound_lookup(tree234(K, V), K, K, V).
:- mode tree234__upper_bound_lookup(in, in, out, out) is det.

:- pred tree234__insert(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__insert(in, in, in, out) is semidet.
% :- mode tree234__insert(di_tree234, in, in, uo_tree234) is semidet.
% :- mode tree234__insert(in, in, in, out) is semidet.

:- pred tree234__set(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__set(di, di, di, uo) is det.
% :- mode tree234__set(di_tree234, in, in, uo_tree234) is det.
:- mode tree234__set(in, in, in, out) is det.

:- func tree234__set(tree234(K, V), K, V) = tree234(K, V).

:- pred tree234__delete(tree234(K, V), K, tree234(K, V)).
:- mode tree234__delete(di, in, uo) is det.
% :- mode tree234__delete(di_tree234, in, uo_tree234) is det.
:- mode tree234__delete(in, in, out) is det.

:- func tree234__delete(tree234(K, V), K) = tree234(K, V).

:- pred tree234__remove(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__remove(di, in, uo, uo) is semidet.
% :- mode tree234__remove(di_tree234, in, out, uo_tree234) is semidet.
:- mode tree234__remove(in, in, out, out) is semidet.

:- pred tree234__remove_smallest(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__remove_smallest(di, uo, uo, uo) is semidet.
% :- mode tree234__remove_smallest(di_tree234, out, out, uo_tree234)
%	is semidet.
:- mode tree234__remove_smallest(in, out, out, out) is semidet.

	% Given a tree234, return a list of all the keys in the tree.
	% The list that is returned is in sorted order.
:- pred tree234__keys(tree234(K, V), list(K)).
:- mode tree234__keys(in, out) is det.

:- func tree234__keys(tree234(K, V)) = list(K).

:- pred tree234__values(tree234(K, V), list(V)).
:- mode tree234__values(in, out) is det.

:- func tree234__values(tree234(K, V)) = list(V).

:- pred tree234__update(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__update(in, in, in, out) is semidet.
% :- mode tree234__update(di_tree234, in, in, uo_tree234) is det.
% :- mode tree234__update(di, di, di, uo) is semidet.

	% count the number of elements in a tree
:- pred tree234__count(tree234(K, V), int).
:- mode tree234__count(in, out) is det.

:- func tree234__count(tree234(K, V)) = int.

:- pred tree234__assoc_list_to_tree234(assoc_list(K, V), tree234(K, V)).
:- mode tree234__assoc_list_to_tree234(in, out) is det.

:- func tree234__assoc_list_to_tree234(assoc_list(K, V)) = tree234(K, V).

	% Given a tree234, return an association list of all the
	% keys and values in the tree.  The association list that
	% is returned is sorted on the keys.
:- pred tree234__tree234_to_assoc_list(tree234(K, V), assoc_list(K, V)).
:- mode tree234__tree234_to_assoc_list(in, out) is det.

:- func tree234__tree234_to_assoc_list(tree234(K, V)) = assoc_list(K, V).

:- pred tree234__foldl(pred(K, V, T, T), tree234(K, V), T, T).
:- mode tree234__foldl(pred(in, in, in, out) is det, in, in, out) is det.
:- mode tree234__foldl(pred(in, in, in, out) is semidet, in, in, out)
	is semidet.
:- mode tree234__foldl(pred(in, in, di, uo) is det, in, di, uo) is det.

:- func tree234__foldl(func(K, V, T) = T, tree234(K, V), T) = T.

:- pred tree234__foldl2(pred(K, V, T, T, U, U), tree234(K, V), T, T, U, U).
:- mode tree234__foldl2(pred(in, in, in, out, in, out) is det,
	in, in, out, in, out) is det.
:- mode tree234__foldl2(pred(in, in, in, out, in, out) is semidet,
	in, in, out, in, out) is semidet.
:- mode tree234__foldl2(pred(in, in, in, out, di, uo) is det,
	in, in, out, di, uo) is det.
:- mode tree234__foldl2(pred(in, in, di, uo, di, uo) is det,
	in, di, uo, di, uo) is det.

:- pred tree234__foldl3(pred(K, V, T, T, U, U, W, W), tree234(K, V),
	T, T, U, U, W, W).
:- mode tree234__foldl3(pred(in, in, in, out, in, out, in, out) is det,
	in, in, out, in, out, in, out) is det.
:- mode tree234__foldl3(pred(in, in, in, out, in, out, in, out) is semidet,
	in, in, out, in, out, in, out) is semidet.
:- mode tree234__foldl3(pred(in, in, in, out, in, out, di, uo) is det,
	in, in, out, in, out, di, uo) is det.
:- mode tree234__foldl3(pred(in, in, in, out, di, uo, di, uo) is det,
	in, in, out, di, uo, di, uo) is det.
:- mode tree234__foldl3(pred(in, in, di, uo, di, uo, di, uo) is det,
	in, di, uo, di, uo, di, uo) is det.

:- pred tree234__map_values(pred(K, V, W), tree234(K, V), tree234(K, W)).
:- mode tree234__map_values(pred(in, in, out) is det, in, out) is det.
:- mode tree234__map_values(pred(in, in, out) is semidet, in, out) is semidet.

:- func tree234__map_values(func(K, V) = W, tree234(K, V)) = tree234(K, W).

:- pred tree234__map_foldl(pred(K, V, W, A, A), tree234(K, V), tree234(K, W),
	A, A).
:- mode tree234__map_foldl(pred(in, in, out, in, out) is det,
	in, out, in, out) is det.
:- mode tree234__map_foldl(pred(in, in, out, in, out) is semidet,
	in, out, in, out) is semidet.

%--------------------------------------------------%
%--------------------------------------------------%


Node:type_desc, Next:, Previous:tree234, Up:Top

61 type_desc


%--------------------------------------------------%
% Copyright (C) 2002-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: type_desc.m.
% Main author: fjh, zs.
% Stability: low.

%--------------------------------------------------%
%--------------------------------------------------%

:- module type_desc.

:- interface.

:- import_module list.

	% The `type_desc' and `type_ctor_desc' types: these
	% provide access to type information.
	% A type_desc represents a type, e.g. `list(int)'.
	% A type_ctor_desc represents a type constructor, e.g. `list/1'.

:- type type_desc.
:- type type_ctor_desc.

	% (Note: it is not possible for the type of a variable to be an
	% unbound type variable; if there are no constraints on a type
	% variable, then the typechecker will use the type `void'.
	% `void' is a special (builtin) type that has no constructors.
	% There is no way of creating an object of type `void'.
	% `void' is not considered to be a discriminated union, so
	% get_functor/5 and construct/3 will fail if used upon a value
	% of this type.)

	% The function type_of/1 returns a representation of the type
	% of its argument.
	%
:- func type_of(T) = type_desc__type_desc.
:- mode type_of(unused) = out is det.

	% The predicate has_type/2 is basically an existentially typed
	% inverse to the function type_of/1.  It constrains the type
	% of the first argument to be the type represented by the
	% second argument.
:- some [T] pred has_type(T::unused, type_desc__type_desc::in) is det.

	% type_name(Type) returns the name of the specified type
	% (e.g. type_name(type_of([2,3])) = "list:list(int)").
	% Any equivalence types will be fully expanded.
	% Builtin types (those defined in builtin.m) will
	% not have a module qualifier.
	%
:- func type_name(type_desc__type_desc) = string.

	% type_ctor_and_args(Type, TypeCtor, TypeArgs):
	%	True iff `TypeCtor' is a representation of the top-level
	%	type constructor for `Type', and `TypeArgs' is a list
	%	of the corresponding type arguments to `TypeCtor',
	%	and `TypeCtor' is not an equivalence type.
	%
	% For example, type_ctor_and_args(type_of([2,3]), TypeCtor,
	% TypeArgs) will bind `TypeCtor' to a representation of the
	% type constructor list/1, and will bind `TypeArgs' to the list
	% `[Int]', where `Int' is a representation of the type `int'.
	%
	% Note that the requirement that `TypeCtor' not be an
	% equivalence type is fulfilled by fully expanding any
	% equivalence types.  For example, if you have a declaration
	% `:- type foo == bar.', then type_ctor_and_args/3 will always
	% return a representation of type constructor `bar/0', not `foo/0'.
	% (If you don't want them expanded, you can use the reverse mode
	% of make_type/2 instead.)
	%
:- pred type_ctor_and_args(type_desc__type_desc::in,
	type_desc__type_ctor_desc::out, list(type_desc__type_desc)::out)
	is det.

	% type_ctor(Type) = TypeCtor :-
	%	type_ctor_and_args(Type, TypeCtor, _).
	%
:- func type_ctor(type_desc__type_desc) = type_desc__type_ctor_desc.

	% type_args(Type) = TypeArgs :-
	%	type_ctor_and_args(Type, _, TypeArgs).
	%
:- func type_args(type_desc__type_desc) = list(type_desc__type_desc).

	% type_ctor_name(TypeCtor) returns the name of specified
	% type constructor.
	% (e.g. type_ctor_name(type_ctor(type_of([2,3]))) = "list").
	%
:- func type_ctor_name(type_desc__type_ctor_desc) = string.

	% type_ctor_module_name(TypeCtor) returns the module name of specified
	% type constructor.
	% (e.g. type_ctor_module_name(type_ctor(type_of(2))) = "builtin").
	%
:- func type_ctor_module_name(type_desc__type_ctor_desc) = string.

	% type_ctor_arity(TypeCtor) returns the arity of specified
	% type constructor.
	% (e.g. type_ctor_arity(type_ctor(type_of([2,3]))) = 1).
	%
:- func type_ctor_arity(type_desc__type_ctor_desc) = int.

	% type_ctor_name_and_arity(TypeCtor, ModuleName, TypeName, Arity) :-
	%	Name = type_ctor_name(TypeCtor),
	%	ModuleName = type_ctor_module_name(TypeCtor),
	%	Arity = type_ctor_arity(TypeCtor).
	%
:- pred type_ctor_name_and_arity(type_desc__type_ctor_desc::in,
	string::out, string::out, int::out) is det.

	% make_type(TypeCtor, TypeArgs) = Type:
	%	True iff `Type' is a type constructed by applying
	%	the type constructor `TypeCtor' to the type arguments
	%	`TypeArgs'.
	%
	% Operationally, the forwards mode returns the type formed by
	% applying the specified type constructor to the specified
	% argument types, or fails if the length of TypeArgs is not the
	% same as the arity of TypeCtor.  The reverse mode returns a
	% type constructor and its argument types, given a type_desc;
	% the type constructor returned may be an equivalence type
	% (and hence this reverse mode of make_type/2 may be more useful
	% for some purposes than the type_ctor/1 function).
	%
:- func make_type(type_desc__type_ctor_desc, list(type_desc__type_desc)) =
	type_desc__type_desc.
:- mode make_type(in, in) = out is semidet.
:- mode make_type(out, out) = in is cc_multi.

	% det_make_type(TypeCtor, TypeArgs):
	%
	% Returns the type formed by applying the specified type
	% constructor to the specified argument types.  Aborts if the
	% length of `TypeArgs' is not the same as the arity of `TypeCtor'.
	%
:- func det_make_type(type_desc__type_ctor_desc, list(type_desc__type_desc)) =
	type_desc__type_desc.

%--------------------------------------------------%


Node:varset, Previous:type_desc, Up:Top

62 varset


%--------------------------------------------------%
% Copyright (C) 1993-2000,2002-2003 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: varset.m.
% Main author: fjh.
% Stability: low.
%
% This file provides facilities for manipulating collections of
% variables and terms.
% It provides the 'varset' ADT. A varset is a set of variables.
% (These variables are object-level variables, and are represented
% as ground terms, so it might help to think of them as "variable ids"
% rather than variables.)
% Associated with each variable there can be both a name and a value
% (binding).
%
% There may be some design flaws in the relationship between varset.m,
% term.m, and graph.m.  Once we have implemented unique modes and
% destructive assignment, we will need to rethink the design;  we may
% end up modifying these modules considerably, or we may end up
% making new single-threaded versions of these modules.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module varset.
:- interface.
:- import_module std_util, term, list, map, set, assoc_list.

:- type varset(T).

:- type varset	==	varset(generic).

	% construct an empty varset.
:- pred varset__init(varset(T)::out) is det.

:- func varset__init = varset(T).

	% check whether a varset is empty.
:- pred varset__is_empty(varset(T)::in) is semidet.

	% create a new variable
:- pred varset__new_var(varset(T)::in, var(T)::out, varset(T)::out) is det.

	% create a new named variable
:- pred varset__new_named_var(varset(T)::in, string::in, var(T)::out,
	varset(T)::out) is det.

	% create a new named variable with a unique (w.r.t. the
	% varset) number appended to the name.
:- pred varset__new_uniquely_named_var(varset(T)::in, string::in, var(T)::out,
	varset(T)::out) is det.

	% create a new variable, and maybe give it a name
:- pred varset__new_maybe_named_var(varset(T)::in, maybe(string)::in,
	var(T)::out, varset(T)::out) is det.

	% create multiple new variables
:- pred varset__new_vars(varset(T)::in, int::in, list(var(T))::out,
	varset(T)::out) is det.

	% delete the name and value for a variable
:- pred varset__delete_var(varset(T)::in, var(T)::in, varset(T)::out) is det.

:- func varset__delete_var(varset(T), var(T)) = varset(T).

	% delete the names and values for a list of variables
:- pred varset__delete_vars(varset(T)::in, list(var(T))::in, varset(T)::out)
	is det.

:- func varset__delete_vars(varset(T), list(var(T))) = varset(T).

	% return a list of all the variables in a varset
:- pred varset__vars(varset(T)::in, list(var(T))::out) is det.

:- func varset__vars(varset(T)) = list(var(T)).

	% set the name of a variable
:- pred varset__name_var(varset(T)::in, var(T)::in, string::in, varset(T)::out)
	is det.

:- func varset__name_var(varset(T), var(T), string) = varset(T).

	% lookup the name of a variable;
	% create one if it doesn't have one using V_ as a prefix
:- pred varset__lookup_name(varset(T)::in, var(T)::in, string::out) is det.

:- func varset__lookup_name(varset(T), var(T)) = string.

	% lookup the name of a variable;
	% create one if it doesn't have one using the specified prefix
:- pred varset__lookup_name(varset(T)::in, var(T)::in, string::in, string::out)
	is det.

:- func varset__lookup_name(varset(T), var(T), string) = string.

	% lookup the name of a variable;
	% fail if it doesn't have one
:- pred varset__search_name(varset(T)::in, var(T)::in, string::out) is semidet.

	% bind a value to a variable
	% (will overwrite any existing binding).
:- pred varset__bind_var(varset(T)::in, var(T)::in, term(T)::in,
	varset(T)::out) is det.

:- func varset__bind_var(varset(T), var(T), term(T)) = varset(T).

	% bind a set of terms to a set of variables.
:- pred varset__bind_vars(varset(T)::in, substitution(T)::in, varset(T)::out)
	is det.

:- func varset__bind_vars(varset(T), substitution(T)) = varset(T).

	% lookup the value of a variable
:- pred varset__search_var(varset(T)::in, var(T)::in, term(T)::out) is semidet.

	% get the bindings for all the bound variables.
:- pred varset__lookup_vars(varset(T)::in, substitution(T)::out) is det.

:- func varset__lookup_vars(varset(T)) = substitution(T).

	% Combine two different varsets, renaming apart:
	% varset__merge(VarSet0, NewVarSet, VarSet, Subst) is
	% true iff VarSet is the varset that results from joining
	% a suitably renamed version of NewVarSet to VarSet0.
	% (Any bindings in NewVarSet are ignored.)
	% Subst is a substitution which maps the variables in NewVarSet
	% into the corresponding fresh variable in VarSet.

:- pred varset__merge_subst(varset(T)::in, varset(T)::in, varset(T)::out,
	substitution(T)::out) is det.

	% varset__merge(VarSet0, NewVarSet, Terms0, VarSet, Terms):
	% As varset__merge_subst, except instead of returning the substitution,
	% this predicate applies it to the given list of terms.

:- pred varset__merge(varset(T)::in, varset(T)::in, list(term(T))::in,
	varset(T)::out, list(term(T))::out) is det.

	% Same as varset__merge_subst, except that the names of variables
	% in NewVarSet are not included in the final varset.
	% This is useful if varset__create_name_var_map needs
	% to be used on the resulting varset.

:- pred varset__merge_subst_without_names(varset(T)::in,
	varset(T)::in, varset(T)::out, substitution(T)::out) is det.

	% Same as varset__merge, except that the names of variables
	% in NewVarSet are not included in the final varset.
	% This is useful if varset__create_name_var_map needs
	% to be used on the resulting varset.

:- pred varset__merge_without_names(varset(T)::in, varset(T)::in,
	list(term(T))::in, varset(T)::out, list(term(T))::out) is det.

	% get the bindings for all the bound variables.
:- pred varset__get_bindings(varset(T)::in, substitution(T)::out) is det.

:- func varset__get_bindings(varset(T)) = substitution(T).

	% set the bindings for all the bound variables.
:- pred varset__set_bindings(varset(T)::in, substitution(T)::in,
	varset(T)::out) is det.

:- func varset__set_bindings(varset(T), substitution(T)) = varset(T).

	% Create a map from names to variables.
	% Each name is mapped to only one variable, even if a name is
	% shared by more than one variable. Therefore this predicate
	% is only really useful if it is already known that no two
	% variables share the same name.
:- pred varset__create_name_var_map(varset(T)::in, map(string, var(T))::out)
	is det.

:- func varset__create_name_var_map(varset(T)) = map(string, var(T)).

	% Return an association list giving the name of each variable.
	% Every variable has an entry in the returned association list,
	% even if it shares its name with another variable.
:- pred varset__var_name_list(varset(T)::in, assoc_list(var(T), string)::out)
	is det.

:- func varset__var_name_list(varset(T)) = assoc_list(var(T), string).

	% Given a list of variable and varset in which some variables have
	% no name but some other variables may have the same name,
	% return another varset in which every variable has a unique name.
	% If necessary, names will have suffixes added on the end;
	% the second argument gives the suffix to use.
:- pred varset__ensure_unique_names(list(var(T))::in,
	string::in, varset(T)::in, varset(T)::out) is det.

:- func varset__ensure_unique_names(list(var(T)), string, varset(T))
	= varset(T).

	% Given a varset and a set of variables, remove the names
	% and values of any other variables stored in the varset.
:- pred varset__select(varset(T)::in, set(var(T))::in, varset(T)::out) is det.

:- func varset__select(varset(T), set(var(T))) = varset(T).

	% Given a varset and a list of variables, construct a new varset
	% containing one variable for each one in the list (and no others).
	% Also return a substitution mapping the selected variables in the
	% original varset into variables in the new varset. The relative
	% ordering of variables in the original varset is maintained.
:- pred varset__squash(varset(T)::in, list(var(T))::in,
	varset(T)::out, map(var(T), var(T))::out) is det.

	% Coerce the types of the variables in a varset.
:- pred varset__coerce(varset(T)::in, varset(U)::out) is det.

:- func varset__coerce(varset(T)) = varset(U).