This is mercury_library.info, produced by makeinfo version 4.11 from
library.texi_pp.

INFO-DIR-SECTION The Mercury Programming Language
START-INFO-DIR-ENTRY
* Mercury Library: (mercury_library).  The Mercury Library Reference Manual.
END-INFO-DIR-ENTRY

   This file documents the Mercury standard library, version 11.07.

   Copyright (C) 1995-1997,1999-2011 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.


File: mercury_library.info,  Node: Top,  Up: (mercury)

Mercury Library Reference Manual, version 11.07
***********************************************

   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".

* Menu:


* array2d::
* array::
* assoc_list::
* bag::
* benchmarking::
* bimap::
* bit_buffer::
* bit_buffer.read::
* bit_buffer.write::
* bitmap::
* bool::
* bt_array::
* builtin::
* calendar::
* char::
* construct::
* cord::
* counter::
* deconstruct::
* digraph::
* dir::
* enum::
* eqvclass::
* erlang_builtin::
* exception::
* float::
* gc::
* getopt_io::
* getopt::
* graph::
* group::
* hash_table::
* injection::
* integer::
* int::
* io::
* lazy::
* lexer::
* library::
* list::
* map::
* math::
* maybe::
* multi_map::
* ops::
* pair::
* parser::
* parsing_utils::
* pprint::
* pqueue::
* pretty_printer::
* prolog::
* queue::
* random::
* rational::
* rbtree::
* relation::
* require::
* rtree::
* set_bbbtree::
* set_ctree234::
* set::
* set_ordlist::
* set_tree234::
* set_unordlist::
* solutions::
* sparse_bitset::
* stack::
* std_util::
* store::
* stream::
* stream.string_writer::
* string.builder::
* string::
* svarray::
* svbag::
* svbimap::
* sveqvclass::
* svlist::
* svmap::
* svmulti_map::
* svpqueue::
* svqueue::
* svrelation::
* svset::
* svstack::
* svvarset::
* table_statistics::
* term_io::
* term::
* term_to_xml::
* thread.channel::
* thread::
* thread.mvar::
* thread.semaphore::
* time::
* tree234::
* tree_bitset::
* type_desc::
* unit::
* univ::
* varset::
* version_array2d::
* version_array::
* version_bitmap::
* version_hash_table::
* version_store::


File: mercury_library.info,  Node: array2d,  Next: array,  Prev: Top,  Up: Top

1 array2d
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2003, 2005-2007, 2011 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: array2d.m.
     % Author: Ralph Becket <rafe@cs.mu.oz.au>.
     % Stability: medium-low.
     %
     % 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 array.
     :- import_module 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).

         % init(M, N, X) = array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]])
         % where each XIJ = X.  An exception is thrown if M < 0 or N < 0.
         %
     :- func init(int, int, T) = array2d(T).
     :- mode init(in, in, 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.
         %
     :- pragma obsolete(new/3).
     :- func new(int, int, T ) = array2d(T).
     :- mode new(in,  in,  in) = array2d_uo is det.

         % 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.

         % A synonym for the above.
         %
     :- func from_lists(list(list(T))) = array2d(T).
     :- mode from_lists(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.

         % Pred version of the above.
         %
     :- pred set(int, int, T,  array2d(T), array2d(T)).
     :- mode set(in,  in,  in, array2d_di, 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.

         % Pred version of the above.
         %
     :- pred unsafe_set(int, int, T,  array2d(T), array2d(T)).
     :- mode unsafe_set(in,  in,  in, array2d_di, 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.

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


File: mercury_library.info,  Node: array,  Next: assoc_list,  Prev: array2d,  Up: Top

2 array
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1993-1995, 1997-2011 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 ways that
     % 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.
     :- import_module maybe.
     :- import_module pretty_printer.
     :- import_module random.

     :- type array(T).

     :- inst array(I) == ground.
     :- inst array == array(ground).

         % 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.
     % :- inst uniq_array == uniq_array(unique).
     :- inst uniq_array(I) == array(I).          % XXX work-around
     :- inst uniq_array == uniq_array(ground).   % XXX work-around

     :- 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).
     % :- inst mostly_uniq_array == mostly_uniq_array(mostly_unique).
     :- inst mostly_uniq_array(I) == array(I).    % XXX work-around
     :- inst mostly_uniq_array == mostly_uniq_array(ground). % XXX work-around

     :- 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.generate(Size, Generate) = Array:
         % Create an array with bounds from 0 to Size - 1 using the function
         % Generate to set the initial value of each element of the array.
         % The initial value of the element at index K will be the result of
         % calling the function Generate(K).
         %
     :- func array.generate(int::in, (func(int) = T)::in) = (array(T)::array_uo)
         is det.

         % array.generate_foldl(Size, Generate, Array, !Acc):
         % As above, but using a predicate with an accumulator threaded through it
         % to generate the initial value of each element.
         %
     :- pred array.generate_foldl(int, pred(int, T, A, A), array(T), A, A).
     :- mode array.generate_foldl(in, in(pred(in, out, in, out) is det),
         array_uo, in, out) is det.
     :- mode array.generate_foldl(in, in(pred(in, out, mdi, muo) is det),
         array_uo, mdi, muo) is det.
     :- mode array.generate_foldl(in, in(pred(in, out, di, uo) is det),
         array_uo, di, uo) is det.
     :- mode array.generate_foldl(in, in(pred(in, out, in, out) is semidet),
         array_uo, in, out) is semidet.
     :- mode array.generate_foldl(in, in(pred(in, out, mdi, muo) is semidet),
         array_uo, mdi, muo) is semidet.
     :- mode array.generate_foldl(in, in(pred(in, out, di, uo) is semidet),
         array_uo, di, uo) is semidet.

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

         % 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.

     :- func array.least_index(array(T)) = int.
     %:- mode array.least_index(array_ui) = out is det.
     :- mode array.least_index(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.

     :- func array.greatest_index(array(T)) = int.
     %:- mode array.greatest_index(array_ui) = out is det.
     :- mode array.greatest_index(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.unsafe_lookup returns the Nth element of an array.
         % It is an error if the index is out of bounds.
         %
     :- pred array.unsafe_lookup(array(T), int, T).
     %:- mode array.unsafe_lookup(array_ui, in, out) is det.
     :- mode array.unsafe_lookup(in, in, out) is det.

         % 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(int, T, array(T), array(T)).
     :- mode array.set(in, in, array_di, array_uo) is det.

         % The same as array.set, except the arguments are in an order
         % that allows the use of state variables.
         %
     :- pred array.svset(int, T, array(T), array(T)).
     :- mode array.svset(in, in, array_di, 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(int, T, array(T), array(T)).
     :- mode array.semidet_set(in, in, array_di, array_uo) is semidet.

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

         % The same as array.unsafe_set, except the arguments are in an order
         % that allows the use of state variables.
         %
     :- pred array.unsafe_svset(int, T, array(T), array(T)).
     :- mode array.unsafe_svset(in, in, array_di, array_uo) is det.

         % 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(int, T, array(T), array(T)).
     %:- mode array.slow_set(in, in, array_ui, 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(int, T, array(T), array(T)).
     %:- mode array.semidet_slow_set(in, in, array_ui, 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.

         % As above, but omit the bounds check.
         %
     :- func array.unsafe_elem(int, array(T)) = T.
     %:- mode array.unsafe_elem(in, array_ui) = out is det.
     :- mode array.unsafe_elem(in, in) = out is det.

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

         % As above, but omit the bounds check.
         %
     :- func 'unsafe_elem :='(int, array(T), T) = array(T).
     :- mode 'unsafe_elem :='(in, array_di, in) = array_uo is det.

         % Returns every element of the array, one by one.
         %
     :- pred array.member(array(T)::in, T::out) is nondet.

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

         % 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(int, T, array(T), array(T)).
     :- mode array.resize(in, in, array_di, 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(int, array(T), array(T)).
     :- mode array.shrink(in, array_di, 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.
         %
     :- func array.from_list(list(T)::in) = (array(T)::array_uo) is det.
     :- pred array.from_list(list(T)::in, array(T)::array_uo) is det.

         % array.from_reverse_list takes a list, and returns an array containing
         % those elements in the reverse order that they occurred in the list.
         %
     :- func array.from_reverse_list(list(T)::in) = (array(T)::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.

         % XXX We prefer users to call the new array.binary_search predicate
         % instead of array.bsearch, which may be deprecated in later releases.
         %
         % 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.approx_binary_search(A, X, I) performs a binary search for an
         % approximate match for X in array A, computing I as the result.  More
         % specifically, if the call succeeds, then either A ^ elem(I) = X or
         % A ^ elem(I) @< X and either X @< A ^ elem(I + 1) or I is the last index
         % in A.
         %
         % array.binary_search(A, X, I) performs a binary search for an
         % exact match for X in array A (i.e., it succeeds iff X = A ^ elem(I)).
         %
         % A must be sorted into ascending order, but may contain duplicates
         % (the ordering must be with respect to the supplied comparison predicate
         % if one is supplied, otherwise with respect to the Mercury standard
         % ordering).
         %
     :- pred array.approx_binary_search(array(T), T, int).
     :- mode array.approx_binary_search(array_ui, in, out) is semidet.

     :- pred array.approx_binary_search(comparison_func(T), array(T), T, int).
     :- mode array.approx_binary_search(in, array_ui, in, out) is semidet.

     :- pred array.binary_search(array(T), T, int).
     :- mode array.binary_search(array_ui, in, out) is semidet.

     :- pred array.binary_search(comparison_func(T), array(T), T, int).
     :- mode array.binary_search(in, array_ui, in, out) is semidet.

         % array.map(Closure, OldArray, NewArray) applies `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.foldl(Pr, Array, !X) is equivalent to
         %   list.foldl(Pr, array.to_list(Array), !X)
         % but more efficient.
         %
     :- pred array.foldl(pred(T1, T2, T2), array(T1), T2, T2).
     :- mode array.foldl(pred(in, in, out) is det, in, in, out) is det.
     :- mode array.foldl(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode array.foldl(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode array.foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode array.foldl(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode array.foldl(pred(in, di, uo) is semidet, in, di, uo) is semidet.

         % array.foldl2(Pr, Array, !X, !Y) is equivalent to
         %   list.foldl2(Pr, array.to_list(Array), !X, !Y)
         % but more efficient.
         %
     :- pred array.foldl2(pred(T1, T2, T2, T3, T3), array(T1), T2, T2, T3, T3).
     :- mode array.foldl2(pred(in, in, out, in, out) is det, in, in, out, in, out)
         is det.
     :- mode array.foldl2(pred(in, in, out, mdi, muo) is det, in, in, out, mdi, muo)
         is det.
     :- mode array.foldl2(pred(in, in, out, di, uo) is det, in, in, out, di, uo)
         is det.
     :- mode array.foldl2(pred(in, in, out, in, out) is semidet, in,
         in, out, in, out) is semidet.
     :- mode array.foldl2(pred(in, in, out, mdi, muo) is semidet, in,
         in, out, mdi, muo) is semidet.
     :- mode array.foldl2(pred(in, in, out, di, uo) is semidet, in,
         in, out, di, uo) is semidet.

         % As above, but with three accumulators.
         %
     :- pred array.foldl3(pred(T1, T2, T2, T3, T3, T4, T4), array(T1),
         T2, T2, T3, T3, T4, T4).
     :- mode array.foldl3(pred(in, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out) is det.
     :- mode array.foldl3(pred(in, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, mdi, muo) is det.
     :- mode array.foldl3(pred(in, in, out, in, out, di, uo) is det,
         in, in, out, in, out, di, uo) is det.
     :- mode array.foldl3(pred(in, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out) is semidet.
     :- mode array.foldl3(pred(in, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldl3(pred(in, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, di, uo) is semidet.

         % As above, but with four accumulators.
         %
     :- pred array.foldl4(pred(T1, T2, T2, T3, T3, T4, T4, T5, T5), array(T1),
         T2, T2, T3, T3, T4, T4, T5, T5).
     :- mode array.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 array.foldl4(pred(in, in, out, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, in, out, mdi, muo) is det.
     :- mode array.foldl4(pred(in, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, di, uo) is det.
     :- mode array.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 array.foldl4(pred(in, in, out, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldl4(pred(in, in, out, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, in, out, di, uo) is semidet.

         % As above, but with five accumulators.
         %
     :- pred array.foldl5(pred(T1, T2, T2, T3, T3, T4, T4, T5, T5, T6, T6),
         array(T1), T2, T2, T3, T3, T4, T4, T5, T5, T6, T6).
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, in, out, in, out, mdi, muo) is det.
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldl5(
         pred(in, in, out, in, out, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, in, out, in, out, di, uo) is semidet.

         % 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.foldr(P, Array, !Acc) is equivalent to
         %   list.foldr(P, array.to_list(Array), !Acc)
         % but more efficient.
         %
     :- pred array.foldr(pred(T1, T2, T2), array(T1), T2, T2).
     :- mode array.foldr(pred(in, in, out) is det, in, in, out) is det.
     :- mode array.foldr(pred(in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode array.foldr(pred(in, di, uo) is det, in, di, uo) is det.
     :- mode array.foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
     :- mode array.foldr(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode array.foldr(pred(in, di, uo) is semidet, in, di, uo) is semidet.

         % As above, but with two accumulators.
         %
     :- pred array.foldr2(pred(T1, T2, T2, T3, T3), array(T1), T2, T2, T3, T3).
     :- mode array.foldr2(pred(in, in, out, in, out) is det, in, in, out, in, out)
         is det.
     :- mode array.foldr2(pred(in, in, out, mdi, muo) is det, in, in, out, mdi, muo)
         is det.
     :- mode array.foldr2(pred(in, in, out, di, uo) is det, in, in, out, di, uo)
         is det.
     :- mode array.foldr2(pred(in, in, out, in, out) is semidet, in,
         in, out, in, out) is semidet.
     :- mode array.foldr2(pred(in, in, out, mdi, muo) is semidet, in,
         in, out, mdi, muo) is semidet.
     :- mode array.foldr2(pred(in, in, out, di, uo) is semidet, in,
         in, out, di, uo) is semidet.

         % As above, but with three accumulators.
         %
     :- pred array.foldr3(pred(T1, T2, T2, T3, T3, T4, T4), array(T1),
         T2, T2, T3, T3, T4, T4).
     :- mode array.foldr3(pred(in, in, out, in, out, in, out) is det, in,
         in, out, in, out, in, out) is det.
     :- mode array.foldr3(pred(in, in, out, in, out, mdi, muo) is det, in,
         in, out, in, out, mdi, muo) is det.
     :- mode array.foldr3(pred(in, in, out, in, out, di, uo) is det, in,
         in, out, in, out, di, uo) is det.
     :- mode array.foldr3(pred(in, in, out, in, out, in, out) is semidet, in,
         in, out, in, out, in, out) is semidet.
     :- mode array.foldr3(pred(in, in, out, in, out, mdi, muo) is semidet, in,
         in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldr3(pred(in, in, out, in, out, di, uo) is semidet, in,
         in, out, in, out, di, uo) is semidet.

         % As above, but with four accumulators.
         %
     :- pred array.foldr4(pred(T1, T2, T2, T3, T3, T4, T4, T5, T5), array(T1),
         T2, T2, T3, T3, T4, T4, T5, T5).
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out) is det.
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, in, out, mdi, muo) is det.
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, di, uo) is det.
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out) is semidet.
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldr4(pred(in, in, out, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, in, out, di, uo) is semidet.

         % As above, but with five accumulators.
         %
     :- pred array.foldr5(pred(T1, T2, T2, T3, T3, T4, T4, T5, T5, T6, T6),
         array(T1), T2, T2, T3, T3, T4, T4, T5, T5, T6, T6).
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out, in, out, in, out) is det.
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, in, out, in, out, mdi, muo) is det.
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, di, uo) is det,
         in, in, out, in, out, in, out, in, out, di, uo) is det.
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out, in, out, in, out) is semidet.
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, in, out, in, out, mdi, muo) is semidet.
     :- mode array.foldr5(
         pred(in, in, out, in, out, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, in, out, in, out, di, uo) is semidet.

         % array.map_foldl(P, A, B, !Acc):
         % Invoke P(Aelt, Belt, !Acc) on each element of the A array,
         % and construct array B from the resulting values of Belt.
         %
     :- pred map_foldl(pred(T1, T2, T3, T3), array(T1), array(T2), T3, T3).
     :- mode map_foldl(in(pred(in, out, in, out) is det),
         in, array_uo, in, out) is det.
     :- mode map_foldl(in(pred(in, out, mdi, muo) is det),
         in, array_uo, mdi, muo) is det.
     :- mode map_foldl(in(pred(in, out, di, uo) is det),
         in, array_uo, di, uo) is det.
     :- mode map_foldl(in(pred(in, out, in, out) is semidet),
         in, array_uo, in, out) is semidet.

         % array.map_corresponding_foldl(P, A, B, C, !Acc):
         %
         % Given two arrays A and B, invoke P(Aelt, Belt, Celt, !Acc) on
         % each corresponding pair of elements Aelt and Belt. Build up the array C
         % from the result Celt values. Return C and the final value of the
         % accumulator.
         %
         % C will have as many elements as A does. In most uses, B will also have
         % this many elements, but may have more; it may NOT have fewer.
         %
     :- pred array.map_corresponding_foldl(pred(T1, T2, T3, T4, T4),
         array(T1), array(T2), array(T3), T4, T4).
     :- mode array.map_corresponding_foldl(
         in(pred(in, in, out, in, out) is det),
         in, in, array_uo, in, out) is det.
     :- mode array.map_corresponding_foldl(
         in(pred(in, in, out, mdi, muo) is det),
         in, in, array_uo, mdi, muo) is det.
     :- mode array.map_corresponding_foldl(
         in(pred(in, in, out, di, uo) is det),
         in, in, array_uo, di, uo) is det.
     :- mode array.map_corresponding_foldl(
         in(pred(in, in, out, in, out) is semidet),
         in, in, array_uo, in, out) is semidet.

         % array.append(A, B) = C:
         %
         % Make C a concatenation of the arrays A and B.
         %
     :- func array.append(array(T)::in, array(T)::in) = (array(T)::array_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_di, array(T)::array_uo,
         random.supply::mdi, random.supply::muo) is det.

         % Convert an array to a pretty_printer.doc for formatting.
         %
     :- func array.array_to_doc(array(T)) = pretty_printer.doc.
     :- mode array.array_to_doc(array_ui) = out is det.

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


File: mercury_library.info,  Node: assoc_list,  Next: bag,  Prev: array,  Up: Top

3 assoc_list
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2010-2011 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.
     :- import_module pair.

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

     :- 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.
         %
     :- func assoc_list.reverse_members(assoc_list(K, V)) = assoc_list(V, K).
     :- pred assoc_list.reverse_members(assoc_list(K, V)::in,
         assoc_list(V, K)::out) is det.

         % Zip together two lists; abort if they are of different lengths.
         %
     :- func assoc_list.from_corresponding_lists(list(K), list(V))
         = assoc_list(K, V).
     :- pred assoc_list.from_corresponding_lists(list(K)::in, list(V)::in,
         assoc_list(K, V)::out) is det.

         % Return the first member of each pair.
         %
     :- func assoc_list.keys(assoc_list(K, V)) = list(K).
     :- pred assoc_list.keys(assoc_list(K, V)::in, list(K)::out) is det.

         % Return the second member of each pair.
         %
     :- func assoc_list.values(assoc_list(K, V)) = list(V).
     :- pred assoc_list.values(assoc_list(K, V)::in, list(V)::out) is det.

         % 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.

         % An alternative version of assoc_list.search.
         %
     :- func assoc_list(K, V) ^ elem(K) = V is semidet.

         % An alternative version of assoc_list.search that throws an
         % exception if the key in question does not appear in the assoc_list.
         %
     :- func assoc_list(K, V) ^ det_elem(K) = V is det.

         % 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.

     :- pred assoc_list.map_keys_only(pred(K, L),
         assoc_list(K, V), assoc_list(L, V)).
     :- mode assoc_list.map_keys_only(pred(in, out) is det, in, out) is det.

     :- func assoc_list.map_keys_only(func(K) = L, assoc_list(K, V))
         = assoc_list(L, V).

     :- pred assoc_list.map_values_only(pred(V, W),
         assoc_list(K, V), assoc_list(K, W)).
     :- mode assoc_list.map_values_only(pred(in, out) is det, in, out) is det.

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

     :- pred assoc_list.map_values(pred(K, V, W),
         assoc_list(K, V), assoc_list(K, W)).
     :- mode assoc_list.map_values(pred(in, in, out) is det, in, out) is det.

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

         % assoc_list.filter(Pred, List, TrueList) takes a closure with one
         % input argument and for each member K - V of List X, calls the closure
         % on the key. K - V is included in TrueList iff Pred(K) is true.
         %
     :- pred assoc_list.filter(pred(K)::in(pred(in) is semidet),
         assoc_list(K, V)::in, assoc_list(K, V)::out) is det.
     :- func assoc_list.filter(pred(K)::in(pred(in) is semidet),
         assoc_list(K, V)::in) = (assoc_list(K, V)::out) is det.

         % assoc_list.negated_filter(Pred, List, FalseList) takes a closure with one
         % input argument and for each member K - V of List X, calls the closure
         % on the key. K - V is included in FalseList iff Pred(K) is false.
         %
     :- pred assoc_list.negated_filter(pred(K)::in(pred(in) is semidet),
         assoc_list(K, V)::in, assoc_list(K, V)::out) is det.
     :- func assoc_list.negated_filter(pred(K)::in(pred(in) is semidet),
         assoc_list(K, V)::in) = (assoc_list(K, V)::out) is det.

         % assoc_list.filter(Pred, List, TrueList, FalseList) takes a closure with
         % one input argument and for each member K - V of List X, calls the closure
         % on the key. K - V is included in TrueList iff Pred(K) is true.
         % K - V is included in FalseList iff Pred(K) is false.
         %
     :- pred assoc_list.filter(pred(K)::in(pred(in) is semidet),
         assoc_list(K, V)::in, assoc_list(K, V)::out, assoc_list(K, V)::out) is det.

         % assoc_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 on the keys.
         %
     :- pred assoc_list.merge(assoc_list(K, V)::in, assoc_list(K, V)::in,
         assoc_list(K, V)::out) is det.
     :- func assoc_list.merge(assoc_list(K, V), assoc_list(K, V))
         = assoc_list(K, V).

         % assoc_list.foldl_keys(Pred, List, Start End) calls Pred
         % with each key in List (working left-to-right) and an accumulator
         % (with initial value of Start), and returns the final value in End.
         %
     :- pred assoc_list.foldl_keys(pred(K, A, A), assoc_list(K, V), A, A).
     :- mode assoc_list.foldl_keys(pred(in, in, out) is det, in,
         in, out) is det.
     :- mode assoc_list.foldl_keys(pred(in, mdi, muo) is det, in,
         mdi, muo) is det.
     :- mode assoc_list.foldl_keys(pred(in, di, uo) is det, in,
         di, uo) is det.
     :- mode assoc_list.foldl_keys(pred(in, in, out) is semidet, in,
         in, out) is semidet.
     :- mode assoc_list.foldl_keys(pred(in, mdi, muo) is semidet, in,
         mdi, muo) is semidet.
     :- mode assoc_list.foldl_keys(pred(in, di, uo) is semidet, in,
         di, uo) is semidet.
     :- mode assoc_list.foldl_keys(pred(in, in, out) is multi, in,
         in, out) is multi.
     :- mode assoc_list.foldl_keys(pred(in, in, out) is nondet, in,
         in, out) is nondet.

         % assoc_list.foldl_values(Pred, List, Start End) calls Pred
         % with each value in List (working left-to-right) and an accumulator
         % (with initial value of Start), and returns the final value in End.
         %
     :- pred assoc_list.foldl_values(pred(V, A, A), assoc_list(K, V), A, A).
     :- mode assoc_list.foldl_values(pred(in, in, out) is det, in,
         in, out) is det.
     :- mode assoc_list.foldl_values(pred(in, mdi, muo) is det, in,
         mdi, muo) is det.
     :- mode assoc_list.foldl_values(pred(in, di, uo) is det, in,
         di, uo) is det.
     :- mode assoc_list.foldl_values(pred(in, in, out) is semidet, in,
         in, out) is semidet.
     :- mode assoc_list.foldl_values(pred(in, mdi, muo) is semidet, in,
         mdi, muo) is semidet.
     :- mode assoc_list.foldl_values(pred(in, di, uo) is semidet, in,
         di, uo) is semidet.
     :- mode assoc_list.foldl_values(pred(in, in, out) is multi, in,
         in, out) is multi.
     :- mode assoc_list.foldl_values(pred(in, in, out) is nondet, in,
         in, out) is nondet.

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


File: mercury_library.info,  Node: bag,  Next: benchmarking,  Prev: assoc_list,  Up: Top

4 bag
*****

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-1999, 2003-2007, 2011 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.
     % Main authors: conway, crs.
     % Stability: medium.
     %
     % An implementation of multisets.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module bag.
     :- interface.

     :- import_module assoc_list.
     :- import_module list.
     :- import_module set.

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

     :- type bag(T).

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

         % Return the number of values in a bag (including duplicate values).
         %
     :- func bag.count(bag(T)) = int.

         % Return the number of unique values in a bag, duplicate values are counted
         % only once.
         %
     :- func bag.count_unique(bag(T)) = int.

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

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

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

         % bag.member(Val, Bag):
         % True iff `Bag' contains at least one occurrence of `Val'.
         %
     :- pred bag.member(T::in, bag(T)::in) is semidet.

         % bag.member(Val, Bag, Remainder):
         % Nondeterministically returns all values from Bag and the
         % corresponding bag after the value has been removed. Duplicate values
         % are returned as many times as they occur in the Bag.
         %
     :- pred bag.member(T::out, bag(T)::in, bag(T)::out) is nondet.

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

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

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

         % 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.
         %
     :- func bag.to_list(bag(T)) = list(T).
     :- pred bag.to_list(bag(T)::in, list(T)::out) is det.

         % 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.
         %
     :- func bag.to_assoc_list(bag(T)) = assoc_list(T, int).
     :- pred bag.to_assoc_list(bag(T)::in, assoc_list(T, int)::out) is det.

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

         % Given a bag, produce a set containing all the values in the bag.
         %
     :- func bag.to_set(bag(T)) = set(T).
     :- func bag.to_set_without_duplicates(bag(T)) = set(T).
     :- pred bag.to_set_without_duplicates(bag(T)::in, set(T)::out) is det.

         % Remove one occurrence of a particular value from a bag.
         % Fail if the item does not exist in the bag.
         %
     :- pred bag.remove(T::in, bag(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.
         %
     :- func bag.det_remove(bag(T), T) = bag(T).
     :- pred bag.det_remove(T::in, bag(T)::in, bag(T)::out) is det.

         % 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(list(T)::in, bag(T)::in, bag(T)::out) is semidet.

         % 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.
         %
     :- func bag.det_remove_list(bag(T), list(T)) = bag(T).
     :- pred bag.det_remove_list(list(T)::in, bag(T)::in, bag(T)::out) is det.

         % Remove a set of values from a bag. Each value is removed once.
         % Fail if any of the items in the set do not exist in the bag.
         %
     :- pred bag.remove_set(set(T)::in, bag(T)::in, bag(T)::out) is semidet.

         % Remove a set of values from a bag. Each value is removed once.
         % Abort if any of the items in the set do not exist in the bag.
         %
     :- func bag.det_remove_set(bag(T), set(T)) = bag(T).
     :- pred bag.det_remove_set(set(T)::in, bag(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.
         %
     :- func bag.delete(bag(T), T) = bag(T).
     :- pred bag.delete(T::in, bag(T)::in, bag(T)::out) is det.

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

         % Delete all occurrences of a particular value from a bag.
         %
     :- func bag.delete_all(bag(T), T) = bag(T).
     :- pred bag.delete_all(T::in, bag(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.
         %
     :- func bag.count_value(bag(T), T) = int.
     :- pred bag.count_value(bag(T)::in, T::in, int::out) is det.

         % 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. An example:
         % bag.subtract({1, 1, 2, 2, 3 }, {1, 1, 2, 3, 3, 3}, {2}).
         %
     :- func bag.subtract(bag(T), bag(T)) = bag(T).
     :- pred bag.subtract(bag(T)::in, bag(T)::in, bag(T)::out) is det.

         % 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.
         %
     :- func bag.union(bag(T), bag(T)) = bag(T).
     :- pred bag.union(bag(T)::in, bag(T)::in, bag(T)::out) is det.

         % 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}).
         %
     :- func bag.intersect(bag(T), bag(T)) = bag(T).
     :- pred bag.intersect(bag(T)::in, bag(T)::in, bag(T)::out) is det.

         % 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.
         %
     :- func bag.least_upper_bound(bag(T), bag(T)) = bag(T).
     :- pred bag.least_upper_bound(bag(T)::in, bag(T)::in, bag(T)::out) is det.

         % Tests whether the first bag is 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(T::out, bag(T)::in, 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.

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


File: mercury_library.info,  Node: benchmarking,  Next: bimap,  Prev: bag,  Up: Top

5 benchmarking
**************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2011 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.
     %
     % This module contains predicates that deal with the CPU time requirements
     % of (various parts of) the program.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module benchmarking.
     :- interface.

     :- import_module io.
     :- import_module maybe.

         % `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.
         %
         % Note: in Java, this reports usage of the calling thread.  You will get
         % nonsensical results if the previous call to `report_stats' was from a
         % different thread.
         %
         % Note: in Erlang, the benchmark_* procedures will change the apparent time
         % of the last call to report_stats.
         %
     :- 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.

         % report_memory_attribution(Label, !IO) is a procedure intended for use in
         % profiling the memory usage by a program. In `memprof.gc' grades it has
         % the side-effect of forcing a garbage collection and reporting a summary
         % of the objects on the heap to a data file. See ``Using mprof -s for
         % profiling memory retention'' in the Mercury User's Guide. The label is
         % for your reference.
         %
         % On other grades this procedure does nothing.
         %
     :- pred report_memory_attribution(string::in, io::di, io::uo) is det.

     :- impure pred report_memory_attribution(string::in) 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.

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

         % Turn off or on the collection of all profiling statistics.
         %
     :- pred turn_off_profiling(io::di, io::uo) is det.
     :- pred turn_on_profiling(io::di, io::uo) is det.

     :- impure pred turn_off_profiling is det.
     :- impure pred turn_on_profiling is det.

         % Turn off or on the collection of call graph profiling statistics.
         %
     :- pred turn_off_call_profiling(io::di, io::uo) is det.
     :- pred turn_on_call_profiling(io::di, io::uo) is det.

     :- impure pred turn_off_call_profiling is det.
     :- impure pred turn_on_call_profiling is det.

         % Turn off or on the collection of time spent in each procedure
         % profiling statistics.
         %
     :- pred turn_off_time_profiling(io::di, io::uo) is det.
     :- pred turn_on_time_profiling(io::di, io::uo) is det.

     :- impure pred turn_off_time_profiling is det.
     :- impure pred turn_on_time_profiling is det.

         % Turn off or on the collection of memory allocated in each procedure
         % profiling statistics.
         %
     :- pred turn_off_heap_profiling(io::di, io::uo) is det.
     :- pred turn_on_heap_profiling(io::di, io::uo) is det.

     :- impure pred turn_off_heap_profiling is det.
     :- impure pred turn_on_heap_profiling is det.

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

         % write_out_trace_counts(FileName, MaybeErrorMsg, !IO):
         %
         % Write out the trace counts accumulated so far in this program's execution
         % to FileName. If successful, set MaybeErrorMsg to "no". If unsuccessful,
         % e.g. because the program wasn't compiled with debugging enabled or
         % because trace counting isn't turned on, then set MaybeErrorMsg to a "yes"
         % wrapper around an error message.
         %
     :- pred write_out_trace_counts(string::in, maybe(string)::out,
         io::di, io::uo) is det.

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

         % Place a log message in the threadscope event stream.  The event will be
         % logged as being generated by the current Mercury Engine.  This is a no-op
         % when threadscope is not available.
         %
     :- pred log_threadscope_message(string::in, io::di, io::uo) is det.

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


File: mercury_library.info,  Node: bimap,  Next: bit_buffer,  Prev: benchmarking,  Up: Top

6 bimap
*******

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 1994-1995, 1997, 1999, 2004-2006, 2008, 2011 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 efficiently look up the Key given the Data.
     % This time efficiency comes at the expense of using twice as much space.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module bimap.
     :- interface.

     :- import_module assoc_list.
     :- import_module list.
     :- import_module map.

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

     :- type bimap(K, V).

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

         % Initialize an empty bimap.
         %
     :- func bimap.init = bimap(K, V).
     :- pred bimap.init(bimap(K, V)::out) is det.

         % Initialize a bimap with the given key-value pair.
         %
     :- func bimap.singleton(K, V) = bimap(K, V).

         % Check whether a bimap is empty.
         %
     :- pred bimap.is_empty(bimap(K, V)::in) is semidet.

         % Search the bimap. The first mode searches for a value given a key
         % and the second mode searches for a key given a value.
         %
     :- pred bimap.search(bimap(K, V), K, V).
     :- mode bimap.search(in, in, out) is semidet.
     :- mode bimap.search(in, out, in) is semidet.

         % Search the bimap for the value corresponding to a given key.
         %
     :- func bimap.forward_search(bimap(K, V), K) = V is semidet.
     :- pred bimap.forward_search(bimap(K, V)::in, K::in, V::out) is semidet.

         % Search the bimap for the key corresponding to the given value.
         %
     :- func bimap.reverse_search(bimap(K, V), V) = K is semidet.
     :- pred bimap.reverse_search(bimap(K, V)::in, K::out, V::in) is semidet.

         % Look up the value in the bimap corresponding to the given key.
         % Throws an exception if the key is not present in the bimap.
         %
     :- func bimap.lookup(bimap(K, V), K) = V.
     :- pred bimap.lookup(bimap(K, V)::in, K::in, V::out) is det.

         % Look up the key in the bimap corresponding to the given value.
         % Throws an exception if the value is not present in the bimap.
         %
     :- func bimap.reverse_lookup(bimap(K, V), V) = K.
     :- pred bimap.reverse_lookup(bimap(K, V)::in, K::out, V::in) is det.

         % Given a bimap, return a list of all the keys in the bimap.
         %
     :- func bimap.ordinates(bimap(K, V)) = list(K).
     :- pred bimap.ordinates(bimap(K, V)::in, list(K)::out) is det.

         % Given a bimap, return a list of all the data values in the bimap.
         %
     :- func bimap.coordinates(bimap(K, V)) = list(V).
     :- pred bimap.coordinates(bimap(K, V)::in, list(V)::out) is det.

         % Succeeds iff the bimap contains the given key.
         %
     :- pred bimap.contains_key(bimap(K, V)::in, K::in) is semidet.

         % Succeeds iff the bimap contains the given value.
         %
     :- pred bimap.contains_value(bimap(K, V)::in, V::in) is semidet.

         % Insert a new key-value pair into the bimap.
         % Fails if either the key or value already exists.
         %
     :- func bimap.insert(bimap(K, V), K, V) = bimap(K, V) is semidet.
     :- pred bimap.insert(K::in, V::in, bimap(K, V)::in, bimap(K, V)::out)
         is semidet.

         % As above but throws an exception if the key or value already
         % exists.
         %
     :- func bimap.det_insert(bimap(K, V), K, V) = bimap(K, V).
     :- pred bimap.det_insert(K::in, V::in, bimap(K, V)::in, bimap(K, V)::out)
         is det.

         % Update the key and value if already present, otherwise insert the
         % new key and value.
         %
         % NOTE: setting the key-value pair (K, V) will remove the key-value pairs
         % (K, V1) and (K1, V) if they exist.
         %
     :- func bimap.set(bimap(K, V), K, V) = bimap(K, V).
     :- pred bimap.set(K::in, V::in, bimap(K, V)::in, bimap(K, V)::out) is det.

         % Insert key-value pairs from an association list into the given bimap.
         % Fails if the contents of the association list and the initial bimap
         % do not implicitly form a bijection.
         %
     :- func bimap.insert_from_assoc_list(assoc_list(K, V), bimap(K, V)) =
         bimap(K, V) is semidet.
     :- pred bimap.insert_from_assoc_list(assoc_list(K, V)::in,
         bimap(K, V)::in, bimap(K, V)::out) is semidet.

         % As above but throws an exception if the association list and
         % initial bimap are not implicitly bijective.
         %
     :- func bimap.det_insert_from_assoc_list(assoc_list(K, V), bimap(K, V))
         = bimap(K, V).
     :- pred bimap.det_insert_from_assoc_list(assoc_list(K, V)::in,
         bimap(K, V)::in, bimap(K, V)::out) is det.

         % Insert key-value pairs from a pair of corresponding lists.
         % Throws an exception if the lists are not of equal lengths
         % or if they do not implicitly define a bijection.
         %
     :- func bimap.det_insert_from_corresponding_lists(list(K), list(V),
         bimap(K, V)) = bimap(K, V).
     :- pred bimap.det_insert_from_corresponding_lists(list(K)::in, list(V)::in,
         bimap(K, V)::in, bimap(K, V)::out) is det.

         % Apply bimap.set to each key-value pair in the association list.
         % The key-value pairs from the association list may update existing keys
         % and values in the bimap.
         %
     :- func bimap.set_from_assoc_list(assoc_list(K, V), bimap(K, V))
         = bimap(K, V).
     :- pred bimap.set_from_assoc_list(assoc_list(K, V)::in,
         bimap(K, V)::in, bimap(K, V)::out) is det.

         % As above but with a pair of corresponding lists in place of an
         % association list. Throws an exception if the lists are not of
         % equal length.
         %
     :- func bimap.set_from_corresponding_lists(list(K), list(V),
         bimap(K, V)) = bimap(K, V).
     :- pred bimap.set_from_corresponding_lists(list(K)::in, list(V)::in,
         bimap(K, V)::in, bimap(K, V)::out) is det.

         % Delete a key-value pair from a bimap. If the key is not present,
         % leave the bimap unchanged.
         %
     :- func bimap.delete_key(bimap(K, V), K) = bimap(K, V).
     :- pred bimap.delete_key(K::in, bimap(K, V)::in, bimap(K, V)::out) is det.

         % Delete a key-value pair from a bimap. If the value is not present,
         % leave the bimap unchanged.
         %
     :- func bimap.delete_value(bimap(K, V), V) = bimap(K, V).
     :- pred bimap.delete_value(V::in, bimap(K, V)::in, bimap(K, V)::out) is det.

         % Apply bimap.delete_key to a list of keys.
         %
     :- func bimap.delete_keys(bimap(K, V), list(K)) = bimap(K, V).
     :- pred bimap.delete_keys(list(K)::in, bimap(K, V)::in, bimap(K, V)::out)
         is det.

         % Apply bimap.delete_value to a list of values.
         %
     :- func bimap.delete_values(bimap(K, V), list(V)) = bimap(K, V).
     :- pred bimap.delete_values(list(V)::in, bimap(K, V)::in, bimap(K, V)::out)
         is det.

         % bimap.overlay(BIMapA, BIMapB, BIMap):
         % Apply map.overlay to the forward maps of BIMapA and BIMapB,
         % and compute the reverse map from the resulting map.
         %
     :- func bimap.overlay(bimap(K, V), bimap(K, V)) = bimap(K, V).
     :- pred bimap.overlay(bimap(K, V)::in, bimap(K, V)::in, bimap(K, V)::out)
         is det.

         % Convert a bimap to an association list.
         %
     :- func bimap.to_assoc_list(bimap(K, V)) = assoc_list(K, V).
     :- pred bimap.to_assoc_list(bimap(K, V)::in, assoc_list(K, V)::out) is det.

         % Convert an association list to a bimap. Fails if the association list
         % does not implicitly define a bijection, i.e. a key or value occurs
         % multiple times in the association list.
         %
     :- func bimap.from_assoc_list(assoc_list(K, V)) = bimap(K, V) is semidet.
     :- pred bimap.from_assoc_list(assoc_list(K, V)::in, bimap(K, V)::out)
         is semidet.

         % As above but throws an exception instead of failing if the
         % association list does not implicitly defined a bijection.
         %
     :- func bimap.det_from_assoc_list(assoc_list(K, V)) = bimap(K, V).
     :- pred bimap.det_from_assoc_list(assoc_list(K, V)::in, bimap(K, V)::out)
         is det.

         % Convert a pair of lists into a bimap. Fails if the lists do not
         % implicitly define a bijection or if the lists are of unequal length.
         %
     :- func bimap.from_corresponding_lists(list(K), list(V)) = bimap(K, V)
         is semidet.
     :- pred bimap.from_corresponding_lists(list(K)::in, list(V)::in,
         bimap(K, V)::out) is semidet.

         % As above but throws an exception instead of failing if the lists
         % do not implicitly define a bijection or are of unequal length.
         %
     :- func bimap.det_from_corresponding_lists(list(K), list(V)) = bimap(K, V).
     :- pred bimap.det_from_corresponding_lists(list(K)::in, list(V)::in,
         bimap(K, V)::out) is det.

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

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

         % Apply a transformation predicate to all the keys.
         % Throws an exception if the resulting bimap is not bijective.
         %
     :- func bimap.map_keys(func(V, K) = L, bimap(K, V)) = bimap(L, V).
     :- pred bimap.map_keys(pred(V, K, L)::in(pred(in, in, out) is det),
         bimap(K, V)::in, bimap(L, V)::out) is det.

         % Apply a transformation predicate to all the values.
         % Throws an exception if the resulting bimap is not bijective.
         %
     :- func bimap.map_values(func(K, V) = W, bimap(K, V)) = bimap(K, W).
     :- pred bimap.map_values(pred(K, V, W)::in(pred(in, in, out) is det),
         bimap(K, V)::in, bimap(K, W)::out) is det.

         % Perform a traversal of the bimap, applying an accumulator predicate
         % for each key-value pair.
         %
     :- func bimap.foldl(func(K, V, A) = A, bimap(K, V), A) = A.
     :- pred bimap.foldl(pred(K, V, A, A), bimap(K, V), A, A).
     :- mode bimap.foldl(pred(in, in, in, out) is det, in, in, out) is det.
     :- mode bimap.foldl(pred(in, in, mdi, muo) is det, in, mdi, muo) is det.
     :- mode bimap.foldl(pred(in, in, di, uo) is det, in, di, uo) is det.
     :- mode bimap.foldl(pred(in, in, in, out) is semidet, in, in, out) is semidet.
     :- mode bimap.foldl(pred(in, in, mdi, muo) is semidet, in, mdi, muo) is semidet.
     :- mode bimap.foldl(pred(in, in, di, uo) is semidet, in, di, uo) is semidet.

         % Perform a traversal of the bimap, applying an accumulator predicate
         % with two accumulators for each key-value pair. (Although no more
         % expressive than bimap.foldl, this is often a more convenient format,
         % and a little more efficient).
         %
     :- pred bimap.foldl2(pred(K, V, A, A, B, B), bimap(K, V), A, A, B, B).
     :- mode bimap.foldl2(pred(in, in, in, out, in, out) is det,
         in, in, out, in, out) is det.
     :- mode bimap.foldl2(pred(in, in, in, out, mdi, muo) is det,
         in, in, out, mdi, muo) is det.
     :- mode bimap.foldl2(pred(in, in, in, out, di, uo) is det,
         in, in, out, di, uo) is det.
     :- mode bimap.foldl2(pred(in, in, di, uo, di, uo) is det,
         in, di, uo, di, uo) is det.
     :- mode bimap.foldl2(pred(in, in, in, out, in, out) is semidet,
         in, in, out, in, out) is semidet.
     :- mode bimap.foldl2(pred(in, in, in, out, mdi, muo) is semidet,
         in, in, out, mdi, muo) is semidet.
     :- mode bimap.foldl2(pred(in, in, in, out, di, uo) is semidet,
         in, in, out, di, uo) is semidet.

         % Perform a traversal of the bimap, applying an accumulator predicate
         % with three accumulators for each key-value pair. (Although no more
         % expressive than bimap.foldl, this is often a more convenient format,
         % and a little more efficient).
         %
     :- pred bimap.foldl3(pred(K, V, A, A, B, B, C, C), bimap(K, V),
         A, A, B, B, C, C).
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, in, out) is det,
         in, in, out, in, out, in, out) is det.
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, mdi, muo) is det,
         in, in, out, in, out, mdi, muo) is det.
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, di, uo) is det,
         in, in, out, in, out, di, uo) is det.
     :- mode bimap.foldl3(pred(in, in, in, out, di, uo, di, uo) is det,
         in, in, out, di, uo, di, uo) is det.
     :- mode bimap.foldl3(pred(in, in, di, uo, di, uo, di, uo) is det,
         in, di, uo, di, uo, di, uo) is det.
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, in, out) is semidet,
         in, in, out, in, out, in, out) is semidet.
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, mdi, muo) is semidet,
         in, in, out, in, out, mdi, muo) is semidet.
     :- mode bimap.foldl3(pred(in, in, in, out, in, out, di, uo) is semidet,
         in, in, out, in, out, di, uo) is semidet.

         % Extract a the forward map from the bimap, the map from key to value.
         %
     :- func bimap.forward_map(bimap(K, V)) = map(K, V).

         % Extract the reverse map from the bimap, the map from value to key.
         %
     :- func bimap.reverse_map(bimap(K, V)) = map(V, K).

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


File: mercury_library.info,  Node: bit_buffer,  Next: bit_buffer.read,  Prev: bimap,  Up: Top

7 bit_buffer
************

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2007, 2009 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: bit_buffer.m.
     % Main author: stayl.
     % Stability: low.
     %
     % A bit buffer provides an interface between bit-oriented I/O requests
     % and byte-oriented streams.  The useful part of the interface is defined
     % in bit_buffer.read and bit_buffer.write.
     %
     % 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 bit_buffer.
     :- interface.

     :- import_module bitmap.
     :- import_module stream.

     :- include_module bit_buffer.read.
     :- include_module bit_buffer.write.

         % An error_stream throws an `error_stream_error' exception if any of
         % its output methods are called, or returns an `error_stream_error'
         % if any of its input methods are called.
         %
     :- type error_stream ---> error_stream.
     :- type error_state ---> error_state.
     :- type error_stream_error ---> error_stream_error.
     :- instance stream.error(error_stream_error).
     :- instance stream.stream(error_stream, error_state).
     :- instance stream.input(error_stream, error_state).
     :- instance stream.bulk_reader(error_stream, byte_index, bitmap,
             error_state, error_stream_error).

     :- instance stream.output(error_stream, error_state).
     :- instance stream.writer(error_stream, bitmap.slice, error_state).

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


File: mercury_library.info,  Node: bit_buffer.read,  Next: bit_buffer.write,  Prev: bit_buffer,  Up: Top

8 bit_buffer.read
*****************

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2007, 2010-2011 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: bit_buffer.read.m.
     % Main author: stayl.
     % Stability: low.
     %
     % A bit buffer provides an interface between bit-oriented input requests
     % and byte-oriented streams, getting a large chunk of bits with one call
     % to `bulk_get', then satisfying bit-oriented requests from the buffer.
     %
     % Return values of `error(...)' are only used for errors in the stream
     % being read.  Once an error value has been returned, all future calls
     % will return that error.
     %
     % Bounds errors or invalid argument errors (for example a read request
     % for a negative number of bits) will result in an exception being thrown.
     % Requests triggering an exception in this way will not change the state
     % of the stream.
     %
     % 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 bit_buffer.read.
     :- interface.

     :- import_module io.

     :- type read_buffer(Stream, State, Error).
             % <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).

     :- type read_buffer ==
                 read_buffer(error_stream, error_state, error_stream_error).

     :- type io_read_buffer ==
                 read_buffer(io.binary_input_stream, io.state, io.error).

     :- inst uniq_read_buffer == ground.   % XXX Should be unique.
     :- mode read_buffer_di == in(uniq_read_buffer).
     :- mode read_buffer_ui == in(uniq_read_buffer).
     :- mode read_buffer_uo == out(uniq_read_buffer).

         % new(NumBytes, Stream, State) creates a buffer which will read from
         % the stream specified by Stream and State in chunks of NumBytes bytes.
         % `NumBytes' must at least the size of a Mercury int, given by
         % int.bits_per_int.  If it is less, the size of an int will be used
         % instead.
         %
     :- func new(num_bytes, Stream, State) = read_buffer(Stream, State, Error)
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode new(in, in, di) = read_buffer_uo is det.

         % new(BitIndex, StartIndex, NumBits)
         % Create a buffer which reads bits from a bitmap, not from a stream.
         %
     :- func new_bitmap_reader(bitmap, bit_index, num_bits) = read_buffer.
     :- mode new_bitmap_reader(in, in, in) = read_buffer_uo is det.

     :- func new_bitmap_reader(bitmap) = read_buffer.
     :- mode new_bitmap_reader(in) = read_buffer_uo is det.

         % How many bits to be read does the buffer contain.
         %
     :- func num_buffered_bits(read_buffer(_, _, _)) = num_bits.
     :- mode num_buffered_bits(read_buffer_ui) = out is det.

         % How many bits need to be read to get to the next byte boundary.
         %
     :- func num_bits_to_byte_boundary(read_buffer(_, _, _)) = num_bits.
     :- mode num_bits_to_byte_boundary(read_buffer_ui) = out is det.

         % Find out whether there are bits left in the stream or an error
         % has been found.
         %
     :- pred buffer_status(stream.result(Error),
         read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode buffer_status(out, read_buffer_di, read_buffer_uo) is det.

         % Read a bit from the buffer.
         %
         % This implements the get/4 method of class stream.reader.
         %
     :- pred get_bit(stream.result(bool, Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bit(out, read_buffer_di, read_buffer_uo) is det.

         % get_bits(Index, NumBits, !Word, NumBitsRead, Result, !Buffer).
         %
         % Read NumBits bits from the buffer into a word starting at Index,
         % where the highest order bit is bit zero.
         % 0 =< NumBits =< int.bits_per_int.
         %
         % This implements the bulk_get/9 method of stream.bulk_reader.
         %
         % To read into the lower order bits of the word, use
         % `get_bits(bits_per_int - NumBits, NumBits, ...)'.
         %
     :- pred get_bits(bit_index, num_bits, word, word, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bits(in, in, di, uo, out, out,
         read_buffer_di, read_buffer_uo) is det.

         % get_bitmap(!Bitmap, NumBitsRead, Result, !Buffer)
         %
         % Fill a bitmap from the buffered stream, returning the number
         % of bits read.
         %
         % Note that this is much more efficient if the initial position in
         % the buffer is at a byte boundary (for example after a call to
         % skip_padding_to_byte).
         %
     :- pred get_bitmap(bitmap, bitmap, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bitmap(bitmap_di, bitmap_uo, out, out,
         read_buffer_di, read_buffer_uo) is det.

         % get_bitmap(Index, NumBits, !Bitmap, NumBitsRead, Result, !Buffer)
         %
         % Note that this is much more efficient if both Index and the initial
         % position in the buffer are both at a byte boundary (for example after
         % a call to skip_padding_to_byte).
         %
         % This implements the bulk_get method of stream.bulk_reader.
         %
     :- pred get_bitmap(bit_index, num_bits, bitmap, bitmap, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bitmap(in, in, bitmap_di, bitmap_uo, out, out,
         read_buffer_di, read_buffer_uo) is det.

         % finalize(Buffer, Stream, State, BufferBM,
         %   IndexInBufferBM, NumBitsInBufferBM)
         %
         % Returns the stream, state and the unread buffered bits.
         %
     :- pred finalize(read_buffer(Stream, State, Error), Stream, State,
         bitmap, bit_index, num_bits)
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode finalize(read_buffer_di, out, uo, bitmap_uo, out, out) is det.

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


File: mercury_library.info,  Node: bit_buffer.write,  Next: bitmap,  Prev: bit_buffer.read,  Up: Top

9 bit_buffer.write
******************

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2007, 2011 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: bit_buffer.write.m.
     % Main author: stayl.
     % Stability: low.
     %
     % A bit buffer provides an interface between bit-oriented output requests
     % and byte-array-oriented streams, storing bits until there are enough bytes
     % to make calling the `put' method on the stream worthwhile.
     %
     % 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 bit_buffer.write.
     :- interface.

     :- import_module io.

     :- type write_buffer(Stream, State).
             % <= stream.writer(Stream, bitmap.slice, State).

     :- type write_buffer == write_buffer(error_stream, error_state).
     :- type io_write_buffer == write_buffer(io.binary_output_stream, io.state).

     :- inst uniq_write_buffer == ground.   % XXX Should be unique.
     :- mode write_buffer_di == in(uniq_write_buffer).
     :- mode write_buffer_ui == in(uniq_write_buffer).
     :- mode write_buffer_uo == out(uniq_write_buffer).

         % new(NumBytes, Stream, State) creates a buffer which will write to
         % the stream specified by Stream and State in chunks of NumBytes bytes.
         % If NumBytes is less than the size of an integer (given by
         % int.bits_per_int), the size of an integer will be used instead.
         %
     :- func new(num_bytes, Stream, State) = write_buffer(Stream, State)
         <= stream.writer(Stream, byte_index, State).
     :- mode new(in, in, di) = write_buffer_uo is det.

         % new(NumBytes)
         % Create a buffer which collects all of the bits written, and does
         % not write them to a stream.  The bits are collected in chunks of
         % size NumBytes bytes, and are written to a bitmap by
         % `finalize_to_bitmap/1'.
     :- func new_bitmap_builder(num_bytes) = write_buffer.
     :- mode new_bitmap_builder(in) = out is det.

         % How many bits to be written does the buffer contain.
         %
     :- func num_buffered_bits(write_buffer(_, _)) = num_bits.
     :- mode num_buffered_bits(write_buffer_ui) = out is det.

         % Return how many bits need to be written to get to a byte boundary
         % in the output stream.
         %
     :- func num_bits_to_byte_boundary(write_buffer(_, _)) = num_bits.
     :- mode num_bits_to_byte_boundary(write_buffer_ui) = out is det.

         % Write a bit to the buffer.
         %
     :- pred put_bit(bool, write_buffer(Stream, State), write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode put_bit(in, write_buffer_di, write_buffer_uo) is det.

         % Write the given number of low-order bits from an int to the buffer.
         % The number of bits must be less than int.bits_per_int.
         %
     :- pred put_bits(word, num_bits, write_buffer(Stream, State),
         write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode put_bits(in, in, write_buffer_di, write_buffer_uo) is det.

         % Write the eight low-order bits from an int to the buffer.
         % The number of bits must be less than int.bits_per_int.
         %
     :- pred put_byte(word, write_buffer(Stream, State),
         write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode put_byte(in, write_buffer_di, write_buffer_uo) is det.

         % Write bits from a bitmap to the buffer.
         % The buffer does not keep a reference to the bitmap.
         %
     :- pred put_bitmap(bitmap, write_buffer(Stream, State),
         write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode put_bitmap(bitmap_ui, write_buffer_di, write_buffer_uo) is det.

     :- pred put_bitmap(bitmap, bit_index, num_bits,
         write_buffer(Stream, State), write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode put_bitmap(bitmap_ui, in, in, write_buffer_di, write_buffer_uo) is det.

         % Flush all complete bytes in the buffer to the output stream.
         % If there is an incomplete final byte it will remain unwritten
         % in the buffer.
         %
     :- pred flush(write_buffer(Stream, State), write_buffer(Stream, State))
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode flush(write_buffer_di, write_buffer_uo) is det.

         % Pad the buffered data out to a byte boundary, flush it to
         % the output stream, then return the Stream and State.
         %
     :- pred finalize(write_buffer(Stream, State), Stream, State)
         <= stream.writer(Stream, bitmap.slice, State).
     :- mode finalize(write_buffer_di, out, uo) is det.

         % Copy the data from a non-streamed write_buffer to a bitmap.
         % The output is not padded to an even number of bits.
         %
     :- func finalize_to_bitmap(write_buffer) = bitmap.
     :- mode finalize_to_bitmap(write_buffer_di) = bitmap_uo is det.

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


File: mercury_library.info,  Node: bitmap,  Next: bool,  Prev: bit_buffer.write,  Up: Top

10 bitmap
*********

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2001-2002, 2004-2007, 2009-2011 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, stayl.
     % 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 bool.
     :- import_module list.

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

         % Type `bitmap' is equivalent to `array(bool)', but is implemented much
         % more efficiently.  Accessing bitmaps as if they are an array of
         % eight bit bytes is especially efficient.
         %
         % See runtime/mercury_types.h for the definition of MR_BitmapPtr for
         % use in foreign code.
         %
         % Comparison of bitmaps first compares the size, if the size is equal
         % then each bit in turn is compared starting from bit zero.
         %
     :- type bitmap.

     :- inst bitmap == ground.
     :- inst uniq_bitmap == bitmap.  % XXX should be unique
     :- mode bitmap_di == in(uniq_bitmap). % XXX should be di
     :- mode bitmap_uo == out(uniq_bitmap).
     :- mode bitmap_ui == in(uniq_bitmap).

         % The exception thrown for any error.
         %
     :- type bitmap_error
         --->    bitmap_error(string).

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

     :- type bit_index == int.
     :- type byte_index == int.
     :- type num_bits == int.
     :- type num_bytes == int.

         % 8 bits stored in the least significant bits of the integer.
         %
     :- type byte == int.

         % An integer interpreted as a vector of int.bits_per_int bits.
         %
     :- type word == int.

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

         % init(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 init(num_bits::in, bool::in) = (bitmap::bitmap_uo) is det.

         % 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.
         %
     :- pragma obsolete(bitmap.new/2).
     :- func new(num_bits, bool) = bitmap.
     :- mode new(in, in) = bitmap_uo is det.

         % A synonym for init(N, no).
         %
     :- func init(num_bits::in) = (bitmap::bitmap_uo) is det.

         % Same as new(N, no).
         %
     :- pragma obsolete(bitmap.new/1).
     :- func new(num_bits) = bitmap.
     :- mode new(in) = bitmap_uo is det.

         % Create a new copy of a bitmap.
         %
     :- func copy(bitmap) = bitmap.
     %:- mode copy(bitmap_ui) = bitmap_uo is det.
     :- mode copy(in) = 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, num_bits, bool) = bitmap.
     :- mode resize(bitmap_di, in, in) = bitmap_uo is det.

         % Shrink a bitmap without copying it into a smaller memory allocation.
         %
     :- func shrink_without_copying(bitmap, num_bits) = bitmap.
     :- mode shrink_without_copying(bitmap_di, in) = bitmap_uo is det.

         % Is the given bit number in range.
         %
     :- pred in_range(bitmap, bit_index).
     %:- mode in_range(bitmap_ui, in) is semidet.
     :- mode in_range(in, in) is semidet.

         % Is the given byte number in range.
         %
     :- pred byte_in_range(bitmap, byte_index).
     %:- mode byte_in_range(bitmap_ui, in) is semidet.
     :- mode byte_in_range(in, in) is semidet.

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

         % Returns the number of bytes in a bitmap, failing if the bitmap
         % has a partial final byte.
         %
     :- func num_bytes(bitmap) = num_bytes.
     %:- mode num_bytes(bitmap_ui) = out is semidet.
     :- mode num_bytes(in) = out is semidet.

         % As above, but throw an exception if the bitmap has a partial final byte.
         %
     :- func det_num_bytes(bitmap) = num_bytes.
     %:- mode det_num_bytes(bitmap_ui) = out is det.
     :- mode det_num_bytes(in) = out is det.

         % Return the number of bits in a byte (always 8).
         %
     :- func bits_per_byte = int.

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

         %
         % Get or set the given bit.
         % The unsafe versions do not check whether the bit is in range.
         %

     :- func bitmap      ^ bit(bit_index)    = bool.
     %:- mode bitmap_ui  ^ bit(in)           = out is det.
     :- mode in          ^ bit(in)           = out is det.

     :- func bitmap      ^ unsafe_bit(bit_index) = bool.
     %:- mode bitmap_ui  ^ unsafe_bit(in)        = out is det.
     :- mode in          ^ unsafe_bit(in)        = out is det.

     :- func (bitmap     ^ bit(bit_index)    := bool)    = bitmap.
     :- mode (bitmap_di  ^ bit(in)           := in)      = bitmap_uo is det.

     :- func (bitmap     ^ unsafe_bit(bit_index) := bool) = bitmap.
     :- mode (bitmap_di  ^ unsafe_bit(in)        := in)   = bitmap_uo is det.

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

         %
         % Bitmap ^ bits(OffSet, NumBits) = Word.
         % The low order bits of Word contain the NumBits bits of BitMap
         % starting at OffSet.
         % 0 =< NumBits =< int.bits_per_int.
         %

     :- func bitmap      ^ bits(bit_index, num_bits) = word.
     %:- mode bitmap_ui  ^ bits(in, in)              = out is det.
     :- mode in          ^ bits(in, in)              = out is det.

     :- func bitmap      ^ unsafe_bits(bit_index, num_bits)  = word.
     %:- mode bitmap_ui  ^ unsafe_bits(in, in)               = out is det.
     :- mode in          ^ unsafe_bits(in, in)               = out is det.

     :- func (bitmap     ^ bits(bit_index, num_bits) := word) = bitmap.
     :- mode (bitmap_di  ^ bits(in, in)              := in)   = bitmap_uo is det.

     :- func (bitmap     ^ unsafe_bits(bit_index, num_bits) := word) = bitmap.
     :- mode (bitmap_di  ^ unsafe_bits(in, in)              := in)   = bitmap_uo
         is det.

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

         %
         % BM ^ byte(ByteNumber)
         % Get or set the given numbered byte (multiply ByteNumber by
         % bits_per_byte to get the bit index of the start of the byte).
         %
         % The bits are stored in or taken from the least significant bits
         % of the integer.
         % The unsafe versions do not check whether the byte is in range.
         %

     :- func bitmap      ^ byte(byte_index) = byte.
     %:- mode bitmap_ui  ^ byte(in) = out is det.
     :- mode in          ^ byte(in) = out is det.

     :- func bitmap      ^ unsafe_byte(byte_index)   = byte.
     %:- mode bitmap_ui  ^ unsafe_byte(in)           = out is det.
     :- mode in          ^ unsafe_byte(in)           = out is det.

     :- func (bitmap     ^ byte(byte_index)  := byte) = bitmap.
     :- mode (bitmap_di  ^ byte(in)          := in)   = bitmap_uo is det.

     :- func (bitmap     ^ unsafe_byte(byte_index)   := byte) = bitmap.
     :- mode (bitmap_di  ^ unsafe_byte(in)           := in)   = bitmap_uo is det.

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

         % Slice = bitmap.slice(BM, StartIndex, NumBits)
         %
         % A bitmap slice represents the sub-range of a bitmap of NumBits bits
         % starting at bit index StartIndex.  Throws an exception if the slice
         % is not within the bounds of the bitmap.
         %
     :- type bitmap.slice.
     :- func bitmap.slice(bitmap, bit_index, num_bits) = bitmap.slice.

         % As above, but use byte indices.
         %
     :- func bitmap.byte_slice(bitmap, byte_index, num_bytes) = bitmap.slice.

         % Access functions for slices.
         %
     :- func slice ^ slice_bitmap = bitmap.
     :- func slice ^ slice_start_bit_index = bit_index.
     :- func slice ^ slice_num_bits = num_bits.

         % As above, but return byte indices, throwing an exception if
         % the slice doesn't start and end on a byte boundary.
         %
     :- func slice ^ slice_start_byte_index = byte_index.
     :- func slice ^ slice_num_bytes = num_bytes.

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

         % Flip the given bit.
         %
     :- func flip(bitmap, bit_index) = bitmap.
     :- mode flip(bitmap_di, in) = bitmap_uo is det.

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

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

         %
         % Set operations; for binary operations the second argument is altered
         % in all cases.  The input bitmaps must have the same size.
         %

     :- 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.
     :- mode union(in, bitmap_di) = bitmap_uo is det.

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

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

     :- func xor(bitmap, bitmap) = bitmap.
     %:- mode xor(bitmap_ui, bitmap_di) = bitmap_uo is det.
     :- mode xor(in, bitmap_di) = bitmap_uo is det.

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

         % Condense a list of bitmaps into a single bitmap.
     :- func append_list(list(bitmap)) = bitmap.
     :- mode append_list(in) = bitmap_uo is det.

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

         %
         % Operations to copy part of a bitmap.
         %

         % copy_bits(SrcBM, SrcStartBit, DestBM, DestStartBit, NumBits)
         %
         % Overwrite NumBits bits in DestBM starting at DestStartBit with
         % the NumBits bits starting at SrcStartBit in SrcBM.
         %
     :- func copy_bits(bitmap, bit_index, bitmap, bit_index, num_bits) = bitmap.
     %:- mode copy_bits(bitmap_ui, in, bitmap_di, in, in) = bitmap_uo is det.
     :- mode copy_bits(in, in, bitmap_di, in, in) = bitmap_uo is det.

         % copy_bits_in_bitmap(BM, SrcStartBit, DestStartBit, NumBits)
         %
         % Overwrite NumBits bits starting at DestStartBit with the NumBits
         % bits starting at SrcStartBit in the same bitmap.
         %
     :- func copy_bits_in_bitmap(bitmap, bit_index, bit_index, num_bits) = bitmap.
     :- mode copy_bits_in_bitmap(bitmap_di, in, in, in) = bitmap_uo is det.

         % copy_bytes(SrcBM, SrcStartByte, DestBM, DestStartByte, NumBytes)
         %
         % Overwrite NumBytes bytes in DestBM starting at DestStartByte with
         % the NumBytes bytes starting at SrcStartByte in SrcBM.
         %
     :- func copy_bytes(bitmap, byte_index, bitmap, byte_index, num_bytes) = bitmap.
     %:- mode copy_bytes(bitmap_ui, in, bitmap_di, in, in) = bitmap_uo is det.
     :- mode copy_bytes(in, in, bitmap_di, in, in) = bitmap_uo is det.

         % copy_bytes_in_bitmap(BM, SrcStartByte, DestStartByte, NumBytes)
         %
         % Overwrite NumBytes bytes starting at DestStartByte with the NumBytes
         % bytes starting at SrcStartByte in the same bitmap.
         %
     :- func copy_bytes_in_bitmap(bitmap, byte_index,
         byte_index, num_bytes) = bitmap.
     :- mode copy_bytes_in_bitmap(bitmap_di, in, in, in) = bitmap_uo is det.

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

         % Convert a bitmap to a string of the form "<length:hex digits>",
         % e.g. "<24:10AFBD>".
         %
     :- func to_string(bitmap) = string.
     %:- mode to_string(bitmap_ui) = out is det.
     :- mode to_string(in) = out is det.

         % Convert a string created by to_string back into a bitmap.
         %
     :- func from_string(string) = bitmap.
     :- mode from_string(in) = bitmap_uo is semidet.

         % Convert a bitmap to a string of `1' and `0' characters, where
         % the bytes are separated by `.'.
         %
     :- func to_byte_string(bitmap) = string.
     %:- mode to_byte_string(bitmap_ui) = out is det.
     :- mode to_byte_string(in) = out is det.

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

         % Compute a hash function for a bitmap.
         %
     :- func hash(bitmap) = int.
     %:- mode hash(bitmap_ui) = out is det.
     :- mode hash(in) = out is det.

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

         %
         % Variations that might be slightly more efficient by not
         % converting bits to bool.
         %

     :- func set(bitmap, bit_index) = bitmap.
     :- mode set(bitmap_di, in) = bitmap_uo is det.

     :- func clear(bitmap, bit_index) = bitmap.
     :- mode clear(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, bit_index).
     %:- mode is_set(bitmap_ui, in) is semidet.
     :- mode is_set(in, in) is semidet.

     :- pred is_clear(bitmap, bit_index).
     %:- 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.
         %

     :- func unsafe_set(bitmap, bit_index) = bitmap.
     :- mode unsafe_set(bitmap_di, in) = bitmap_uo is det.

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

     :- pred unsafe_set(bit_index, bitmap, bitmap).
     :- mode unsafe_set(in, bitmap_di, bitmap_uo) is det.

     :- pred unsafe_clear(bit_index, bitmap, bitmap).
     :- mode unsafe_clear(in, bitmap_di, bitmap_uo) is det.

     :- pred unsafe_flip(bit_index, bitmap, bitmap).
     :- mode unsafe_flip(in, bitmap_di, bitmap_uo) is det.

     :- pred unsafe_is_set(bitmap, bit_index).
     %:- mode unsafe_is_set(bitmap_ui, in) is semidet.
     :- mode unsafe_is_set(in, in) is semidet.

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

         %
         % Predicate versions, for use with state variables.
         %

     :- pred set(bit_index, bitmap, bitmap).
     :- mode set(in, bitmap_di, bitmap_uo) is det.

     :- pred clear(bit_index, bitmap, bitmap).
     :- mode clear(in, bitmap_di, bitmap_uo) is det.

     :- pred flip(bit_index, bitmap, bitmap).
     :- mode flip(in, bitmap_di, bitmap_uo) is det.

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


File: mercury_library.info,  Node: bool,  Next: bt_array,  Prev: bitmap,  Up: Top

11 bool
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1996-1997,2000,2002-2007,2009-2010 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.
     :- import_module 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).

         % or(A, B) = yes iff A = yes, or B = yes, or both.
         %
     :- func bool.or(bool, bool) = bool.
     :- pred bool.or(bool::in, bool::in, bool::out) is det.

         % or_list(As) = yes iff there exists an element of As equal to yes.
         % (Note that or_list([]) = no.)
         %
     :- func bool.or_list(list(bool)) = bool.
     :- pred bool.or_list(list(bool)::in, bool::out) is det.

         % and(A, B) = yes iff A = yes and B = yes.
         %
     :- func bool.and(bool, bool) = bool.
     :- pred bool.and(bool::in, bool::in, bool::out) is det.

         % and_list(As) = yes iff every element of As is equal to yes.
         % (Note that and_list([]) = yes.)
         %
     :- func bool.and_list(list(bool)) = bool.
     :- pred bool.and_list(list(bool)::in, bool::out) is det.

         % not(A) = yes iff A = no.
         %
     :- func bool.not(bool) = bool.
     :- pred bool.not(bool::in, bool::out) is det.

         % xor(A, B) = yes iff A = yes, or B = yes, but not both.
         %
     :- func bool.xor(bool, bool) = bool.

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

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


File: mercury_library.info,  Node: bt_array,  Next: builtin,  Prev: bool,  Up: Top

12 bt_array
***********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1997, 1999-2000, 2002-2003, 2005-2006 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 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::in, bt_array(T)::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::in, int::in, T::in, bt_array(T)::out) is det.
     :- 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)::in, int::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)::in, int::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)::in, int::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)::in, int::out, int::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)::in, int::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)::in, int::in, T::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)::in, int::in, T::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)::in, int::in, T::in, bt_array(T)::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)::in, int::in, T::in,
         bt_array(T)::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)::in, int::in, int::in, T::in,
         bt_array(T)::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)::in, int::in, int::in, bt_array(T)::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::in, list(T)::in, bt_array(T)::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)::in, list(T)::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)::in, int::in, int::in, list(T)::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)::in, T::in,
         comparison_pred(T)::in(comparison_pred), int::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 'elem :='(int, bt_array(T), T) = bt_array(T).

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


File: mercury_library.info,  Node: builtin,  Next: calendar,  Prev: bt_array,  Up: Top

13 builtin
**********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2007, 2010-2011 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 that use the
         % C interface.
         %
         % NOTE: we strongly recommend using a `foreign_type' pragma instead
         %       of using this type.
         %
     :- 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'.
     %
     % Higher-order predicate insts `pred(<modes>) is <detism>'
     % and higher-order functions insts `func(<modes>) = <mode> is det'
     % are also builtin.

         % 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.  The insts `new' and `old' are allowed as synonyms for
         % `free' and `any', respectively, since some of the literature uses
         % this terminology.
         %
     :- inst old == any.
     :- inst new == free.

     %--------------------------------------------------%
     %
     % 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
     %

     % XXX 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 they 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.

     %--------------------------------------------------%
     %
     % Dynamic modes
     %

         % Solver type modes.
         %
     :- mode ia == any >> any.
     :- mode oa == free >> any.

         % The modes `no' and `oo' are allowed as synonyms, since some of the
         % literature uses this terminology.
         %
     :- mode no == new >> old.
     :- mode oo == old >> old.

     %--------------------------------------------------%
     %
     % Predicates
     %

         % 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!)
         %
     :- func unsafe_promise_unique(T::in) = (T::uo) is det.
     :- pred unsafe_promise_unique(T::in, T::uo) is det.

         % A synonym for fail/0; this name is more in keeping with Mercury's
         % declarative style rather than its Prolog heritage.
         %
     :- pred false is failure.

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

         % This function is useful for converting polymorphic non-solver type
         % values with inst any to inst ground (the compiler recognises that
         % inst any is equivalent to ground for non-polymorphic non-solver
         % type values.)
         %
         % Do not call this on solver type values unless you are absolutely
         % sure that they are semantically ground.
         %
     :- func unsafe_cast_any_to_ground(T::ia) = (T::out) is det.

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

         % 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!)
         %
         % NOTE: we recommend using the a `promise_equivalent_solutions' goal
         %       instead of this function.
         %
     :- 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!)
         %
         % NOTE: we recommend using a `promise_equivalent_solutions' goal
         %       instead of this predicate.
         %
     :- pred promise_only_solution_io(
         pred(T, IO, IO)::in(pred(out, di, uo) is cc_multi), T::out,
         IO::di, IO::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 whether
         % 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

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

         % `semidet_succeed' is exactly the same as `true', exception that
         % the compiler thinks that it is semi-deterministic.  You can use
         % calls to `semidet_succeed' to suppress warnings about determinism
         % declarations that could be stricter.
         %
     :- pred semidet_succeed is semidet.

         % `semidet_fail' is like `fail' except that its determinism is semidet
         % rather than failure.
         %
     :- pred semidet_fail is semidet.

         % A synonym for semidet_succeed/0.
         %
     :- pred semidet_true is semidet.

         % A synonym for semidet_fail/0
         %
     :- pred semidet_false is semidet.

         % `cc_multi_equal(X, Y)' is the same as `X = Y' except that it
         % is cc_multi rather than det.
         %
     :- pred cc_multi_equal(T, T).
     :- mode cc_multi_equal(di, uo) is cc_multi.
     :- mode cc_multi_equal(in, out) is cc_multi.

         % `impure_true' is like `true' except that it is impure.
         %
     :- impure pred impure_true is det.

         % `semipure_true' is like `true' except that it is semipure.
         %
     :- semipure pred semipure_true is det.

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

         % dynamic_cast(X, Y) succeeds with Y = X iff X has the same ground type
         % as Y (so this may succeed if Y is of type list(int), say, but not if
         % Y is of type list(T)).
         %
     :- pred dynamic_cast(T1::in, T2::out) is semidet.

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


File: mercury_library.info,  Node: calendar,  Next: char,  Prev: builtin,  Up: Top

14 calendar
***********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2009-2011 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: calendar.m.
     % Main authors: maclarty
     % Stability: low.
     %
     % Proleptic Gregorian calendar utilities.
     %
     % The Gregorian calendar is the calendar that is currently used by most of
     % the world. In this calendar a year is a leap year if it is divisible by
     % 4, but not divisible by 100. The only exception is if the year is divisible
     % by 400, in which case it is a leap year. For example 1900 is not leap year,
     % while 2000 is. The proleptic Gregorian calendar is an extension of the
     % Gregorian calendar backward in time to before it was first introduced in
     % 1582.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module calendar.
     :- interface.

     :- import_module io.

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

         % A point on the Proleptic Gregorian calendar, to the nearest microsecond.
         %
     :- type date.

         % Date components.
         %
     :- type year == int.         % Year 0 is 1 BC, -1 is 2 BC, etc.
     :- type day_of_month == int. % 1..31 depending on the month and year
     :- type hour == int.         % 0..23
     :- type minute == int.       % 0..59
     :- type second == int.       % 0..61 (60 and 61 are for leap seconds)
     :- type microsecond == int.  % 0..999999

     :- type month
         --->    january
         ;       february
         ;       march
         ;       april
         ;       may
         ;       june
         ;       july
         ;       august
         ;       september
         ;       october
         ;       november
         ;       december.

     :- type day_of_week
         --->    monday
         ;       tuesday
         ;       wednesday
         ;       thursday
         ;       friday
         ;       saturday
         ;       sunday.

         % Functions to retrieve the components of a date.
         %
     :- func year(date) = year.
     :- func month(date) = month.
     :- func day_of_month(date) = day_of_month.
     :- func day_of_week(date) = day_of_week.
     :- func hour(date) = hour.
     :- func minute(date) = minute.
     :- func second(date) = second.
     :- func microsecond(date) = microsecond.

         % init_date(Year, Month, Day, Hour, Minute, Second, MicroSecond, Date).
         % Initialize a new date. Fails if the given date is invalid.
         %
     :- pred init_date(year::in, month::in, day_of_month::in, hour::in,
         minute::in, second::in, microsecond::in, date::out) is semidet.

         % Same as above, but aborts if the date is invalid.
         %
     :- func det_init_date(year, month, day_of_month, hour, minute, second,
         microsecond) = date.

         % Retrieve all the components of a date.
         %
     :- pred unpack_date(date::in,
         year::out, month::out, day_of_month::out, hour::out, minute::out,
         second::out, microsecond::out) is det.

         % Convert a string of the form "YYYY-MM-DD HH:MM:SS.mmmmmm" to a date.
         % The microseconds component (.mmmmmm) is optional.
         %
     :- pred date_from_string(string::in, date::out) is semidet.

         % Same as above, but aborts if the string is not a valid date.
         %
     :- func det_date_from_string(string) = date.

         % Convert a date to a string of the form "YYYY-MM-DD HH:MM:SS.mmmmmm".
         % If the microseconds component of the date is zero, then the
         % ".mmmmmm" part is omitted.
         %
     :- func date_to_string(date) = string.

         % Get the current local time.
         %
     :- pred current_local_time(date::out, io::di, io::uo) is det.

         % Get the current UTC time.
         %
     :- pred current_utc_time(date::out, io::di, io::uo) is det.

         % Calculate the Julian day number for a date on the Gregorian calendar.
         %
     :- func julian_day_number(date) = int.

         % Returns 1970/01/01 00:00:00.
         %
     :- func unix_epoch = date.

         % A period of time measured in years, months, days, hours, minutes,
         % seconds and microseconds. Internally a duration is represented
         % using only months, days, seconds and microseconds components.
         %
     :- type duration.

         % Duration components.
         %
     :- type years == int.
     :- type months == int.
     :- type days == int.
     :- type hours == int.
     :- type minutes == int.
     :- type seconds == int.
     :- type microseconds == int.

         % Functions to retrieve duration components.
         %
     :- func years(duration) = years.
     :- func months(duration) = months.
     :- func days(duration) = days.
     :- func hours(duration) = hours.
     :- func minutes(duration) = minutes.
     :- func seconds(duration) = seconds.
     :- func microseconds(duration) = microseconds.

         % init_duration(Years, Months, Days, Hours, Minutes,
         %   Seconds, MicroSeconds) = Duration.
         % Create a new duration. All of the components should either be
         % non-negative or non-positive (they can all be zero).
         %
     :- func init_duration(years, months, days, hours, minutes, seconds,
         microseconds) = duration.

         % Retrieve all the components of a duration.
         %
     :- pred unpack_duration(duration::in, years::out, months::out,
         days::out, hours::out, minutes::out, seconds::out, microseconds::out)
         is det.

         % Return the zero length duration.
         %
     :- func zero_duration = duration.

         % Negate a duration.
         %
     :- func negate(duration) = duration.

         % Parse a duration string.
         %
         % The string should be of the form "PnYnMnDTnHnMnS" where each "n" is a
         % non-negative integer representing the number of years (Y), months (M),
         % days (D), hours (H), minutes (M) or seconds (S). The duration string
         % always starts with 'P' and the 'T' separates the date and time components
         % of the duration. A component may be omitted if it is zero, and the 'T'
         % separator is not required if all the time components are zero.
         % The second component may include a fraction component using a period.
         % This fraction component should not have a resolution higher than a
         % microsecond.
         %
         % For example the duration 1 year, 18 months, 100 days, 10 hours, 15
         % minutes 90 seconds and 300 microseconds can be written as:
         %   P1Y18M100DT10H15M90.0003S
         % while the duration 1 month and 2 days can be written as:
         %   P1M2D
         %
         % Note that internally the duration is represented using only months,
         % days, seconds and microseconds, so that
         % duration_to_string(det_duration_from_string("P1Y18M100DT10H15M90.0003S"))
         % will result in the string "P2Y6M100DT10H16M30.0003S".
         %
     :- pred duration_from_string(string::in, duration::out) is semidet.

         % Same as above, but aborts if the duration string is invalid.
         %
     :- func det_duration_from_string(string) = duration.

         % Convert a duration to a string using the same representation
         % parsed by duration_from_string.
         %
     :- func duration_to_string(duration) = string.

         % Add a duration to a date.
         %
         % First the years and months are added to the date.
         % If this causes the day to be out of range (e.g. April 31), then it is
         % decreased until it is in range (e.g. April 30). Next the remaining
         % days, hours, minutes and seconds components are added. These could
         % in turn cause the month and year components of the date to change again.
         %
     :- pred add_duration(duration::in, date::in, date::out) is det.

         % This predicate implements a partial order relation on durations.
         % DurationA is less than or equal to DurationB iff for all of the
         % dates list below, adding DurationA to the date results in a date
         % less than or equal to the date obtained by adding DurationB.
         %
         %    1696-09-01 00:00:00
         %    1697-02-01 00:00:00
         %    1903-03-01 00:00:00
         %    1903-07-01 00:00:00
         %
         % There is only a partial order on durations, because some durations
         % cannot be said to be less than, equal to or greater than another duration
         % (e.g. 1 month vs. 30 days).
         %
     :- pred duration_leq(duration::in, duration::in) is semidet.

         % Get the difference between local and UTC time as a duration.
         %
         % local_time_offset(TZ, !IO) is equivalent to:
         %   current_local_time(Local, !IO),
         %   current_utc_time(UTC, !IO),
         %   TZ = duration(UTC, Local)
         % except that it is as if the calls to current_utc_time and
         % current_local_time occurred at the same instant.
         %
         % To convert UTC time to local time, add the result of local_time_offset/3
         % to UTC (using add_duration/3). To compute UTC given the local time,
         % first negate the result of local_time_offset/3 (using negate/1) and then
         % add it to the local time.
         %
     :- pred local_time_offset(duration::out, io::di, io::uo) is det.

         % duration(DateA, DateB) = Duration.
         % Find the duration between two dates using a "greedy" algorithm.
         % The algorithm is greedy in the sense that it will try to maximise each
         % component in the returned duration in the following order: years, months,
         % days, hours, minutes, seconds, microseconds.
         % The returned duration is positive if DateB is after DateA and negative
         % if DateB is before DateA.
         % Any leap seconds that occurred between the two dates are ignored.
         % The dates should be in the same timezone and in the same daylight
         % savings phase. To work out the duration between dates in different
         % timezones or daylight savings phases, first convert the dates to UTC.
         %
         % If the seconds components of DateA and DateB are < 60 then
         % add_duration(DateA, duration(DateA, DateB), DateB) will hold, but
         % add_duration(DateB, negate(duration(DateA, DateB)), DateA) may not hold.
         % For example if:
         %   DateA = 2001-01-31
         %   DateB = 2001-02-28
         %   Duration = 1 month
         % then the following holds:
         %   add_duration(duration(DateA, DateB), DateA, DateB)
         % but the following does not:
         %   add_duration(negate(duration(DateA, DateB), DateB, DateA)
         % (Adding -1 month to 2001-02-28 will yield 2001-01-28).
         %
     :- func duration(date, date) = duration.

         % Same as above, except that the year and month components of the
         % returned duration will always be zero. The duration will be in terms
         % of days, hours, minutes, seconds and microseconds only.
         %
     :- func day_duration(date, date) = duration.

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


File: mercury_library.info,  Node: char,  Next: construct,  Prev: calendar,  Up: Top

15 char
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-2008, 2011 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.
     :- import_module list.
     :- import_module pretty_printer.

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

         % A Unicode code point.
         %
     :- type char == character.

     :- instance enum(character).

         % `char.to_int'/1 and `char.to_int(in, out)' convert a character to its
         % corresponding numerical code (integer value).
         %
         % `char.to_int(out, in)' converts an integer value to a character value.
         % It fails for integer values outside of the Unicode range.
         %
         % Be aware that there is no guarantee that characters can be written to
         % files or to the standard output or standard error streams. Files using an
         % 8-bit national character set would only be able to represent a subset of
         % all possible code points. Currently, the Mercury standard library can
         % only read and write UTF-8 text files, so the entire range is supported
         % (excluding surrogate and noncharacter code points).
         %
         % Note that '\0' is not accepted as a Mercury null character literal.
         % Instead, a null character can be created using `char.det_from_int(0)'.
         % Null characters are not allowed in Mercury strings in C grades.
         %
     :- 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.

         % Converts an integer to its corresponding character, if any.
         % A more expressive name for the reverse mode of char.to_int.
         %
     :- pred char.from_int(int::in, char::out) is semidet.

         % Converts an integer to its corresponding character. Aborts
         % if there isn't one.
         %
     :- pred char.det_from_int(int::in, char::out) is det.
     :- func char.det_from_int(int) = char.

         % 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.
         % Note that this only converts unaccented Latin letters.
         %
     :- func char.to_upper(char) = char.
     :- pred char.to_upper(char::in, char::out) is det.

         % Convert a character to lowercase.
         % Note that this only converts unaccented Latin letters.
         %
     :- 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, and both Lower and Upper are unaccented
         % Latin letters.
         %
     :- 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 a whitespace character in the ASCII range,
         % 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.

     :- pred char.is_hex_digit(char, int).
     :- mode char.is_hex_digit(in, out) is semidet.

         % Convert an integer 0-15 to a hexadecimal digit 0-9, A-F.
         %
     :- pred char.int_to_hex_char(int, char).
     :- mode char.int_to_hex_char(in, out) 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.

         % Convert a char to a pretty_printer.doc for formatting.
         %
     :- func char.char_to_doc(char) = pretty_printer.doc.

         % Encode a Unicode code point in UTF-8.
         % Fails for surrogate code points.
         %
     :- pred char.to_utf8(char::in, list(int)::out) is semidet.

         % Encode a Unicode code point in UTF-16 (native endianness).
         % Fails for surrogate code points.
         %
     :- pred char.to_utf16(char::in, list(int)::out) is semidet.

         % Succeed if `Char' is a Unicode surrogate code point.
         % In UTF-16, a code point with a scalar value greater than 0xffff
         % is encoded with a pair of surrogate code points.
         %
     :- pred char.is_surrogate(char::in) is semidet.

         % Succeed if `Char' is a Noncharacter code point.
         % Sixty-six code points are not used to encode characters.
         % These code points should not be used for interchange, but may be used
         % internally.
         %
     :- pred char.is_noncharacter(char::in) is semidet.

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


File: mercury_library.info,  Node: construct,  Next: cord,  Prev: char,  Up: Top

16 construct
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 2002-2009, 2011 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 list.
     :- import_module maybe.
     :- import_module univ.
     :- import_module type_desc.

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

         % 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.
         %
     :- type functor_number_ordinal == int.
     :- type functor_number_lex == int.

         % num_functors(Type).
         %
         % Returns the number of different functors for the top-level
         % type constructor of the type specified by Type.
         % Fails if the type is not a discriminated union type.
         %
         % deconstruct.functor_number/3, deconstruct.deconstruct_du/5
         % and the semidet predicates and functions in this module will
         % only succeed for types for which num_functors/1 succeeds.
         %
     :- func num_functors(type_desc) = int is semidet.

     :- func det_num_functors(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::in, functor_number_lex::in,
         string::out, int::out, list(pseudo_type_desc)::out) is semidet.

         % get_functor_with_names(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_with_names(type_desc::in, functor_number_lex::in,
         string::out, int::out, list(pseudo_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.
         %
     :- func get_functor_ordinal(type_desc, functor_number_lex) =
         functor_number_ordinal is semidet.
     :- pred get_functor_ordinal(type_desc::in, functor_number_lex::in,
         functor_number_ordinal::out) is semidet.

         % get_functor_lex(Type, Ordinal) = I.
         %
         % Returns I, where I is the position in lexicographic order for the
         % specified type of the function symbol that is in position Ordinal
         % in declaration order. Fails if the type is not a discriminated
         % union type, or if Ordinal is out of range.
         %
     :- func get_functor_lex(type_desc, functor_number_ordinal) =
         functor_number_lex is semidet.

         % find_functor(Type, FunctorName, Arity, FunctorNumber, ArgTypes).
         %
         % Given a type descriptor, a functor name and arity, finds the functor
         % number and the types of its arguments. It thus serves as the converse
         % to get_functor/5.
         %
     :- pred find_functor(type_desc::in, string::in, int::in,
         functor_number_lex::out, list(type_desc)::out) is semidet.

         % construct(Type, I, Args) = Term.
         %
         % Returns a term of the type specified by Type whose functor
         % is functor number I of the type given by Type, 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, functor_number_lex, list(univ)) = univ is semidet.

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

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


File: mercury_library.info,  Node: cord,  Next: counter,  Prev: construct,  Up: Top

17 cord
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 2002-2011 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: cord.m.
     % Author: Ralph Becket <rafe@cs.mu.oz.au>
     % Stability: medium.
     %
     % A cord is a 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.

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

         % 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).

         % Return the empty cord.
         %
     :- func init = cord(T).

         % The unique representation for the empty cord:
         %
         %   list(empty) = []
         %
     :- func empty = 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).

         % rev_list(Cord) = list.reverse(list(Cord).
         %
     :- func rev_list(cord(T)) = list(T).

         % Succeed iff the given cord is empty.
         %
     :- pred is_empty(cord(T)::in) is semidet.

         % 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).

         % Append together a list of cords.
         %
     :- func cord_list_to_cord(list(cord(T))) = cord(T).

         % Append together a list of cords, and return the result as a list.
         %
     :- func cord_list_to_list(list(cord(T))) = list(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.

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

         %     get_first(C0, X)  =>  some [C]: list(C0) = [X] ++ C.
         % not get_first(C0, _)  =>  C0 = empty
         %
     :- pred get_first(cord(T)::in, T::out) is semidet.

         %     get_last(C0, X)  =>  some [C]: list(C0) = C ++ [X].
         % not get_last(C0, _)  =>  C0 = empty
         %
     :- pred get_last(cord(T)::in, 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).
     :- pred map_pred(pred(T, U)::in(pred(in, out) is det),
         cord(T)::in, cord(U)::out) is det.

         % filter(Pred, Cord, TrueCord):
         %
         % Pred is a closure with one input argument.
         % For each member X of Cord,
         % - Pred(X) is true, then X is included in TrueCord.
         %
     :- pred filter(pred(T)::in(pred(in) is semidet),
         cord(T)::in, cord(T)::out) is det.

         % filter(Pred, Cord, TrueCord, FalseCord):
         %
         % Pred is a closure with one input argument.
         % For each member X of Cord,
         % - Pred(X) is true, then X is included in TrueCord.
         % - Pred(X) is false, then X is included in FalseCord.
         %
     :- pred filter(pred(T)::in(pred(in) is semidet),
         cord(T)::in, cord(T)::out, cord(T)::out) is det.

         % foldl(F, C, A) = list.foldl(F, list(C), A).
         %
     :- func foldl(func(T, U) = U, cord(T), U) = U.
     :- pred foldl_pred(pred(T, U, U), cord(T), U, U).
     :- mode foldl_pred(in(pred(in, in, out) is det), in, in, out) is det.
     :- mode foldl_pred(in(pred(in, mdi, muo) is det), in, mdi, muo) is det.
     :- mode foldl_pred(in(pred(in, di, uo) is det), in, di, uo) is det.
     :- mode foldl_pred(in(pred(in, in, out) is semidet), in, in, out) is semidet.
     :- mode foldl_pred(in(pred(in, mdi, muo) is semidet), in, mdi, muo) is semidet.
     :- mode foldl_pred(in(pred(in, di, uo) is semidet), in, di, uo) is semidet.

         % foldr(F, C, A) = list.foldr(F, list(C), A).
         %
     :- func foldr(func(T, U) = U, cord(T), U) = U.
     :- pred foldr_pred(pred(T, U, U), cord(T), U, U).
     :- mode foldr_pred(in(pred(in, in, out) is det), in, in, out) is det.
     :- mode foldr_pred(in(pred(in, mdi, muo) is det), in, mdi, muo) is det.
     :- mode foldr_pred(in(pred(in, di, uo) is det), in, di, uo) is det.
     :- mode foldr_pred(in(pred(in, in, out) is semidet), in, in, out) is semidet.
     :- mode foldr_pred(in(pred(in, mdi, muo) is semidet), in, mdi, muo) is semidet.
     :- mode foldr_pred(in(pred(in, di, uo) is semidet), in, di, uo) is semidet.

         % map_foldl(P, CA, CB, !Acc):
         %
         % This predicate calls P on each element of the input cord, working
         % left to right. Each call to P transforms an element of the input cord
         % to the corresponding element of the output cord, and updates the
         % accumulator.
         %
     :- pred map_foldl(pred(A, B, C, C), cord(A), cord(B), C, C).
     :- mode map_foldl(in(pred(in, out, in, out) is det), in, out, in, out)
         is det.
     :- mode map_foldl(in(pred(in, out, mdi, muo) is det), in, out, mdi, muo)
         is det.
     :- mode map_foldl(in(pred(in, out, di, uo) is det), in, out, di, uo)
         is det.
     :- mode map_foldl(in(pred(in, out, in, out) is semidet), in, out, in, out)
         is semidet.
     :- mode map_foldl(in(pred(in, out, mdi, muo) is semidet), in, out, mdi, muo)
         is semidet.
     :- mode map_foldl(in(pred(in, out, di, uo) is semidet), in, out, di, uo)
         is semidet.

         % As above, but with two accumulators.
         %
     :- pred map_foldl2(pred(A, B, C, C, D, D)::
         in(pred(in, out, in, out, in, out) is det),
         cord(A)::in, cord(B)::out, C::in, C::out, D::in, D::out) is det.

         % As above, but with three accumulators.
         %
     :- pred map_foldl3(pred(A, B, C, C, D, D, E, E)::
         in(pred(in, out, in, out, in, out, in, out) is det),
         cord(A)::in, cord(B)::out, C::in, C::out, D::in, D::out, E::in, E::out)
         is det.

         % 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.

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


File: mercury_library.info,  Node: counter,  Next: deconstruct,  Prev: cord,  Up: Top

18 counter
**********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2000, 2005-2006, 2011 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.

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


File: mercury_library.info,  Node: deconstruct,  Next: digraph,  Prev: counter,  Up: Top

19 deconstruct
**************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 2002-2007 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 construct.
     :- import_module list.
     :- import_module maybe.
     :- import_module univ.

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

         % 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.
     :- inst do_not_allow_or_include_details_cc
         --->    do_not_allow
         ;       include_details_cc.

         % 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>>.
         %   - for c_pointers, the string ptr(0xXXXX) where XXXX is the
         %     hexadecimal representation of the pointer.
         %   - for bitmaps, the bitmap converted to a a length and a
         %     hexadecimal string inside angle brackets and quotes of the
         %     form """<[0-9]:[0-9A-F]*>""".
         %
         % 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.
         %   - for c_pointers, zero.
         %   - for bitmaps, zero.
         %
         % 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.

         % functor_number(Data, FunctorNumber, Arity)
         %
         % Given a data item, return the number of the functor,
         % suitable for use by construct.construct, and the arity.
         % Fail if the item does not have a discriminated union type.
         % Abort if the type has user-defined equality.
         %
     :- pred functor_number(T::in, functor_number_lex::out, int::out) is semidet.

         % functor_number_cc(Data, FunctorNumber, Arity)
         %
         % Given a data item, return the number of the functor,
         % suitable for use by construct.construct, and the arity.
         % Fail if the item does not have a discriminated union type.
         % Don't abort if the type has user-defined equality.
         %
     :- pred functor_number_cc(T::in, functor_number_lex::out,
         int::out) is cc_nondet.

         % 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.

     :- type maybe_arg
         --->    some [T] arg(T)
         ;       no_arg.

         % arg_cc/3 is similar to arg/4, except that it handles arguments with
         % non-canonical types.  The possible non-existence of an argument is
         % encoded using a maybe type.
         %
     :- pred arg_cc(T::in, int::in, maybe_arg::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::in, string::in, maybe_arg::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.

         % deconstruct_du(Data, NonCanon, FunctorNumber, Arity, Arguments)
         %
         % Given a data item (Data) which has a discriminated union type, binds
         % FunctorNumber to the number of the functor in lexicographic order,
         % 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.
         %
         % Fails if Data does not have discriminated union type.
         %
     :- pred deconstruct_du(T, noncanon_handling, functor_number_lex,
         int, list(univ)).
     :- mode deconstruct_du(in, in(do_not_allow), out, out, out) is semidet.
     :- mode deconstruct_du(in, in(include_details_cc), out, out, out) is cc_nondet.
     :- mode deconstruct_du(in, in, out, out, out) is cc_nondet.

         % 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.

     :- pred limited_deconstruct_cc(T::in, int::in,
         maybe({string, int, list(univ)})::out) is cc_multi.

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


File: mercury_library.info,  Node: digraph,  Next: dir,  Prev: deconstruct,  Up: Top

20 digraph
**********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1995-1999,2002-2007, 2010-2011 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: digraph.m
     % Main author: bromage, petdr
     % Stability: medium
     %
     % This module defines a data type representing directed graphs.  A directed
     % graph of type digraph(T) is logically equivalent to a set of vertices of
     % type T, and a set of edges of type pair(T).  The endpoints of each edge
     % must be included in the set of vertices; cycles and loops are allowed.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module digraph.
     :- interface.

     :- import_module assoc_list.
     :- import_module enum.
     :- import_module list.
     :- import_module map.
     :- import_module pair.
     :- import_module set.
     :- import_module sparse_bitset.

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

         % The type of directed graphs with vertices in T.
         %
     :- type digraph(T).

         % The abstract type that indexes vertices in a digraph.  Each key is only
         % valid with the digraph it was created from -- predicates and functions
         % in this module may throw an exception if an invalid key is used.
         %
     :- type digraph_key(T).

     :- instance enum(digraph_key(T)).

     :- type digraph_key_set(T) == sparse_bitset(digraph_key(T)).

         % digraph.init creates an empty digraph.
         %
     :- func digraph.init = digraph(T).
     :- pred digraph.init(digraph(T)::out) is det.

         % digraph.add_vertex adds a vertex to the domain of a digraph.
         % Returns the old key if one already exists for this vertex, or
         % else allocates a new key.
         %
     :- pred digraph.add_vertex(T::in, digraph_key(T)::out,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.search_key returns the key associated with a vertex.  Fails if
         % the vertex is not in the graph.
         %
     :- pred digraph.search_key(digraph(T)::in, T::in, digraph_key(T)::out)
         is semidet.

         % digraph.lookup_key returns the key associated with a vertex.  Aborts if
         % the vertex is not in the graph.
         %
     :- func digraph.lookup_key(digraph(T), T) = digraph_key(T).
     :- pred digraph.lookup_key(digraph(T)::in, T::in, digraph_key(T)::out)
         is det.

         % digraph.lookup_vertex returns the vertex associated with a key.
         %
     :- func digraph.lookup_vertex(digraph(T), digraph_key(T)) = T.
     :- pred digraph.lookup_vertex(digraph(T)::in, digraph_key(T)::in, T::out)
         is det.

         % digraph.add_edge adds an edge to the digraph if it doesn't already
         % exist, and leaves the digraph unchanged otherwise.
         %
     :- func digraph.add_edge(digraph_key(T), digraph_key(T), digraph(T)) =
         digraph(T).
     :- pred digraph.add_edge(digraph_key(T)::in, digraph_key(T)::in,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.add_vertices_and_edge adds a pair of vertices and an edge
         % between them to the digraph.
         %
         % digraph.add_vertices_and_edge(X, Y, !G) :-
         %    digraph.add_vertex(X, XKey, !G),
         %    digraph.add_vertex(Y, YKey, !G),
         %    digraph.add_edge(XKey, YKey, !G).
         %
     :- func digraph.add_vertices_and_edge(T, T, digraph(T)) = digraph(T).
     :- pred digraph.add_vertices_and_edge(T::in, T::in,
         digraph(T)::in, digraph(T)::out) is det.

         % As above, but takes a pair of vertices in a single argument.
         %
     :- func digraph.add_vertex_pair(pair(T), digraph(T)) = digraph(T).
     :- pred digraph.add_vertex_pair(pair(T)::in,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.add_assoc_list adds a list of edges to a digraph.
         %
     :- func digraph.add_assoc_list(assoc_list(digraph_key(T), digraph_key(T)),
         digraph(T)) = digraph(T).
     :- pred digraph.add_assoc_list(assoc_list(digraph_key(T), digraph_key(T))::in,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.delete_edge deletes an edge from the digraph if it exists,
         % and leaves the digraph unchanged otherwise.
         %
     :- func digraph.delete_edge(digraph_key(T), digraph_key(T), digraph(T)) =
         digraph(T).
     :- pred digraph.delete_edge(digraph_key(T)::in, digraph_key(T)::in,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.delete_assoc_list deletes a list of edges from a digraph.
         %
     :- func digraph.delete_assoc_list(assoc_list(digraph_key(T), digraph_key(T)),
         digraph(T)) = digraph(T).
     :- pred digraph.delete_assoc_list(
         assoc_list(digraph_key(T), digraph_key(T))::in,
         digraph(T)::in, digraph(T)::out) is det.

         % digraph.is_edge checks to see if an edge is in the digraph.
         %
     :- pred digraph.is_edge(digraph(T), digraph_key(T), digraph_key(T)).
     :- mode digraph.is_edge(in, in, out) is nondet.
     :- mode digraph.is_edge(in, in, in) is semidet.

         % digraph.is_edge_rev is equivalent to digraph.is_edge, except that
         % the nondet mode works in the reverse direction.
         %
     :- pred digraph.is_edge_rev(digraph(T), digraph_key(T), digraph_key(T)).
     :- mode digraph.is_edge_rev(in, out, in) is nondet.
     :- mode digraph.is_edge_rev(in, in, in) is semidet.

         % Given key x, digraph.lookup_from returns the set of keys y such that
         % there is an edge (x,y) in the digraph.
         %
     :- func digraph.lookup_from(digraph(T), digraph_key(T)) = set(digraph_key(T)).
     :- pred digraph.lookup_from(digraph(T)::in, digraph_key(T)::in,
         set(digraph_key(T))::out) is det.

         % As above, but returns a digraph_key_set.
         %
     :- func digraph.lookup_key_set_from(digraph(T), digraph_key(T)) =
         digraph_key_set(T).
     :- pred digraph.lookup_key_set_from(digraph(T)::in, digraph_key(T)::in,
         digraph_key_set(T)::out) is det.

         % Given a key y, digraph.lookup_to returns the set of keys x such that
         % there is an edge (x,y) in the digraph.
         %
     :- func digraph.lookup_to(digraph(T), digraph_key(T)) = set(digraph_key(T)).
     :- pred digraph.lookup_to(digraph(T)::in, digraph_key(T)::in,
         set(digraph_key(T))::out) is det.

         % As above, but returns a digraph_key_set.
         %
     :- func digraph.lookup_key_set_to(digraph(T), digraph_key(T)) =
         digraph_key_set(T).
     :- pred digraph.lookup_key_set_to(digraph(T)::in, digraph_key(T)::in,
         digraph_key_set(T)::out) is det.

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

         % digraph.to_assoc_list turns a digraph into a list of pairs of vertices,
         % one for each edge.
         %
     :- func digraph.to_assoc_list(digraph(T)) = assoc_list(T, T).
     :- pred digraph.to_assoc_list(digraph(T)::in, assoc_list(T, T)::out) is det.

         % digraph.to_key_assoc_list turns a digraph into a list of pairs of keys,
         % one for each edge.
         %
     :- func digraph.to_key_assoc_list(digraph(T)) =
         assoc_list(digraph_key(T), digraph_key(T)).
     :- pred digraph.to_key_assoc_list(digraph(T)::in,
         assoc_list(digraph_key(T), digraph_key(T))::out) is det.

         % digraph.from_assoc_list turns a list of pairs of vertices into a digraph.
         %
     :- func digraph.from_assoc_list(assoc_list(T, T)) = digraph(T).
     :- pred digraph.from_assoc_list(assoc_list(T, T)::in, digraph(T)::out) is det.

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

         % digraph.dfs(G, Key, Dfs) is true if Dfs is a depth-first sorting of G
         % starting at Key.  The set of keys in the list Dfs is equal to the
         % set of keys reachable from Key.
         %
     :- func digraph.dfs(digraph(T), digraph_key(T)) = list(digraph_key(T)).
     :- pred digraph.dfs(digraph(T)::in, digraph_key(T)::in,
         list(digraph_key(T))::out) is det.

         % digraph.dfsrev(G, Key, DfsRev) is true if DfsRev is a reverse
         % depth-first sorting of G starting at Key.  The set of keys in the
         % list DfsRev is equal to the set of keys reachable from Key.
         %
     :- func digraph.dfsrev(digraph(T), digraph_key(T)) = list(digraph_key(T)).
     :- pred digraph.dfsrev(digraph(T)::in, digraph_key(T)::in,
         list(digraph_key(T))::out) is det.

         % digraph.dfs(G, Dfs) is true if Dfs is a depth-first sorting of G,
         % i.e. a list of all the keys in G such that all keys for children of
         % a vertex are placed in the list before the parent key.  If the
         % digraph is cyclic, the position in which cycles are broken (that is,
         % in which a child is placed *after* its parent) is undefined.
         %
     :- func digraph.dfs(digraph(T)) = list(digraph_key(T)).
     :- pred digraph.dfs(digraph(T)::in, list(digraph_key(T))::out) is det.

         % digraph.dfsrev(G, DfsRev) is true if DfsRev is a reverse depth-first
         % sorting of G.  That is, DfsRev is the reverse of Dfs from digraph.dfs/2.
         %
     :- func digraph.dfsrev(digraph(T)) = list(digraph_key(T)).
     :- pred digraph.dfsrev(digraph(T)::in, list(digraph_key(T))::out) is det.

         % digraph.dfs(G, Key, !Visit, Dfs) is true if Dfs is a depth-first
         % sorting of G starting at Key, assuming we have already visited !.Visit
         % vertices.  That is, Dfs is a list of vertices such that all the
         % unvisited children of a vertex are placed in the list before the
         % parent.  !.Visit allows us to initialise a set of previously visited
         % vertices.  !:Visit is Dfs + !.Visit.
         %
     :- pred digraph.dfs(digraph(T)::in, digraph_key(T)::in, digraph_key_set(T)::in,
         digraph_key_set(T)::out, list(digraph_key(T))::out) is det.

         % digraph.dfsrev(G, Key, !Visit, DfsRev) is true if DfsRev is a
         % reverse depth-first sorting of G starting at Key providing we have
         % already visited !.Visit nodes, ie the reverse of Dfs from digraph.dfs/5.
         % !:Visit is !.Visit + DfsRev.
         %
     :- pred digraph.dfsrev(digraph(T)::in, digraph_key(T)::in,
         digraph_key_set(T)::in, digraph_key_set(T)::out,
         list(digraph_key(T))::out) is det.

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

         % digraph.vertices returns the set of vertices in a digraph.
         %
     :- func digraph.vertices(digraph(T)) = set(T).
     :- pred digraph.vertices(digraph(T)::in, set(T)::out) is det.

         % digraph.inverse(G, G') is true iff the domains of G and G' are equal,
         % and for all x, y in this domain, (x,y) is an edge in G iff (y,x) is
         % an edge in G'.
         %
     :- func digraph.inverse(digraph(T)) = digraph(T).
     :- pred digraph.inverse(digraph(T)::in, digraph(T)::out) is det.

         % digraph.compose(G1, G2, G) is true if G is the composition
         % of the digraphs G1 and G2.  That is, there is an edge (x,y) in G iff
         % there exists vertex m such that (x,m) is in G1 and (m,y) is in G2.
         %
     :- func digraph.compose(digraph(T), digraph(T)) = digraph(T).
     :- pred digraph.compose(digraph(T)::in, digraph(T)::in, digraph(T)::out)
         is det.

         % digraph.is_dag(G) is true iff G is a directed acyclic graph.
         %
     :- pred digraph.is_dag(digraph(T)::in) is semidet.

         % digraph.components(G, Comp) is true if Comp is the set of the
         % connected components of G.
         %
     :- func digraph.components(digraph(T)) = set(set(digraph_key(T))).
     :- pred digraph.components(digraph(T)::in, set(set(digraph_key(T)))::out)
         is det.

         % digraph.cliques(G, Cliques) is true if Cliques is the set of the
         % cliques (strongly connected components) of G.
         %
     :- func digraph.cliques(digraph(T)) = set(set(digraph_key(T))).
     :- pred digraph.cliques(digraph(T)::in, set(set(digraph_key(T)))::out) is det.

         % digraph.reduced(G, R) is true if R is the reduced digraph (digraph of
         % cliques) obtained from G.
         %
     :- func digraph.reduced(digraph(T)) = digraph(set(T)).
     :- pred digraph.reduced(digraph(T)::in, digraph(set(T))::out) is det.

         % As above, but also return a map from each key in the original digraph
         % to the key for its clique in the reduced digraph.
         %
     :- pred digraph.reduced(digraph(T)::in, digraph(set(T))::out,
         map(digraph_key(T), digraph_key(set(T)))::out) is det.

         % digraph.tsort(G, TS) is true if TS is a topological sorting of G.
         % It fails if G is cyclic.
         %
     :- pred digraph.tsort(digraph(T)::in, list(T)::out) is semidet.

         % digraph.atsort(G, ATS) is true if ATS is a topological sorting
         % of the cliques in G.
         %
     :- func digraph.atsort(digraph(T)) = list(set(T)).
     :- pred digraph.atsort(digraph(T)::in, list(set(T))::out) is det.

         % digraph.sc(G, SC) is true if SC is the symmetric closure of G.
         % That is, (x,y) is in SC iff either (x,y) or (y,x) is in G.
         %
     :- func digraph.sc(digraph(T)) = digraph(T).
     :- pred digraph.sc(digraph(T)::in, digraph(T)::out) is det.

         % digraph.tc(G, TC) is true if TC is the transitive closure of G.
         %
     :- func digraph.tc(digraph(T)) = digraph(T).
     :- pred digraph.tc(digraph(T)::in, digraph(T)::out) is det.

         % digraph.rtc(G, RTC) is true if RTC is the reflexive transitive closure
         % of G.
         %
     :- func digraph.rtc(digraph(T)) = digraph(T).
     :- pred digraph.rtc(digraph(T)::in, digraph(T)::out) is det.

         % digraph.traverse(G, ProcessVertex, ProcessEdge) will traverse a digraph
         % calling ProcessVertex for each vertex in the digraph and ProcessEdge for
         % each edge in the digraph.  Each vertex is processed followed by all the
         % edges originating at that vertex, until all vertices have been processed.
         %
     :- pred digraph.traverse(digraph(T), pred(T, A, A), pred(T, T, A, A), A, A).
     :- mode digraph.traverse(in, pred(in, di, uo) is det,
         pred(in, in, di, uo) is det, di, uo) is det.
     :- mode digraph.traverse(in, pred(in, in, out) is det,
         pred(in, in, in, out) is det, in, out) is det.

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


File: mercury_library.info,  Node: dir,  Next: enum,  Prev: digraph,  Up: Top

21 dir
******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1994-1995,1997,1999-2000,2002-2011 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.
     % Stability: high.
     %
     % Filename and directory handling.
     %
     % 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.

     %--------------------------------------------------%
     %
     % 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 throws an exception instead of failing.
         %
     :- func dir.det_basename(string) = string.

         % A synonym for the above.
         %
     :- pragma obsolete(dir.basename_det/1).
     :- 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.

         % relative_path_name_from_components(List) = PathName.
         %
         % Return the relative pathname from the components in the list.  The
         % components of the list must not contain directory separators.
         %
     :- func dir.relative_path_name_from_components(list(string)) = string.

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

         % dir.current_directory(Result)
         % Return the current working directory.
         %
     :- pred dir.current_directory(io.res(string)::out, io::di, io::uo) is det.

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

         % 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).

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


File: mercury_library.info,  Node: enum,  Next: eqvclass,  Prev: dir,  Up: Top

22 enum
*******

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2000, 2005-2006 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: medium
     %
     % This module provides the typeclass `enum', which describes types
     % which can be converted to and from integers without loss of information.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module enum.
     :- interface.

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

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


File: mercury_library.info,  Node: eqvclass,  Next: erlang_builtin,  Prev: enum,  Up: Top

23 eqvclass
***********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1995-1997, 1999, 2003-2006, 2011 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 list.
     :- import_module set.

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

     :- type eqvclass(T).
     :- type partition_id.

         % Create an empty equivalance class.
         %
     :- func eqvclass.init = eqvclass(T).
     :- pred eqvclass.init(eqvclass(T)::out) is det.

         % Is this item known to the equivalence class?
         %
     :- pred eqvclass.is_member(eqvclass(T)::in, T::in) is semidet.

         % If this item is known to the equivalence class, return the id of its
         % partition. The only use that the caller can make of the partition id
         % is to check whether two items in the same equivalence calls have the
         % same partition id; that test will succeed if and only if the two
         % items are in the same partition. Partition ids are not guaranteed
         % to stay the same as an eqvclass is updated, so such comparisons will
         % work only against the same eqvclass.
         %
         % If you want to check whether two items are in the same equivalence class,
         % using eqvclass.same_eqvclass is more expressive than calling
         % eqvclass.partition_id on both items and comparing the results.
         % However, if you want to perform this check on X and Y1, on X and Y2,
         % ... X and Yn, then calling eqvclass.partition_id on X just once and
         % comparing this with the partition_ids of the Yi will be more efficient.
         %
     :- pred eqvclass.partition_id(eqvclass(T)::in, T::in, partition_id::out)
         is semidet.

         % Make this item known to the equivalence class if it isn't already,
         % and return the id of its partition. The same proviso applies with
         % respect to partition_ids as with eqvclass.partition_id.
         %
     :- pred eqvclass.ensure_element_partition_id(T::in, partition_id::out,
         eqvclass(T)::in, eqvclass(T)::out) is det.

         % 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.
         %
     :- func eqvclass.ensure_element(eqvclass(T), T) = eqvclass(T).
     :- pred eqvclass.ensure_element(T::in, eqvclass(T)::in, eqvclass(T)::out)
         is det.

         % 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.
         %
     :- func eqvclass.new_element(eqvclass(T), T) = eqvclass(T).
     :- pred eqvclass.new_element(T::in, eqvclass(T)::in, eqvclass(T)::out) is det.

         % Make two elements of the equivalence class equivalent.
         % It is ok if they already are.
         %
     :- func eqvclass.ensure_equivalence(eqvclass(T), T, T) = eqvclass(T).
     :- pred eqvclass.ensure_equivalence(T::in, T::in,
         eqvclass(T)::in, eqvclass(T)::out) is det.

     :- func eqvclass.ensure_corresponding_equivalences(list(T), list(T),
         eqvclass(T)) = eqvclass(T).
     :- pred eqvclass.ensure_corresponding_equivalences(list(T)::in, list(T)::in,
         eqvclass(T)::in, eqvclass(T)::out) is det.

         % Make two elements of the equivalence class equivalent.
         % It is an error if they are already equivalent.
         %
     :- func eqvclass.new_equivalence(eqvclass(T), T, T) = eqvclass(T).
     :- pred eqvclass.new_equivalence(T::in, T::in,
         eqvclass(T)::in, eqvclass(T)::out) is det.

         % Test if two elements are equivalent.
         %
     :- pred eqvclass.same_eqvclass(eqvclass(T)::in, T::in, T::in) is semidet.

         % Test if a list of elements are equivalent.
         %
     :- pred eqvclass.same_eqvclass_list(eqvclass(T)::in, list(T)::in) is semidet.

         % Return the set of the partitions of the equivalence class.
         %
     :- func eqvclass.partition_set(eqvclass(T)) = set(set(T)).
     :- pred eqvclass.partition_set(eqvclass(T)::in, set(set(T))::out) is det.

         % Return a list of the partitions of the equivalence class.
         %
     :- func eqvclass.partition_list(eqvclass(T)) = list(set(T)).
     :- pred eqvclass.partition_list(eqvclass(T)::in, list(set(T))::out) is det.

         % Create an equivalence class from a partition set.
         % It is an error if the sets are not disjoint.
         %
     :- func eqvclass.partition_set_to_eqvclass(set(set(T))) = eqvclass(T).
     :- pred eqvclass.partition_set_to_eqvclass(set(set(T))::in, eqvclass(T)::out)
         is det.

         % Create an equivalence class from a list of partitions.
         % It is an error if the sets are not disjoint.
         %
     :- func eqvclass.partition_list_to_eqvclass(list(set(T))) = eqvclass(T).
     :- pred eqvclass.partition_list_to_eqvclass(list(set(T))::in,
         eqvclass(T)::out) is det.

         % Return the set of elements equivalent to the given element.
         % This set will of course include the given element.
         %
     :- func eqvclass.get_equivalent_elements(eqvclass(T), T) = set(T).

         % Return the smallest element equivalent to the given element.
         % This may or may not be the given element.
         %
     :- func eqvclass.get_minimum_element(eqvclass(T), T) = T.

         % Remove the given element and all other elements equivalent to it
         % from the given equivalence class.
         %
     :- func eqvclass.remove_equivalent_elements(eqvclass(T), T) = eqvclass(T).
     :- pred eqvclass.remove_equivalent_elements(T::in,
         eqvclass(T)::in, eqvclass(T)::out) is det.

         % Given a function, divide each partition in the original equivalence class
         % so that two elements of the original partition end up in the same
         % partition in the new equivalence class if and only if the function maps
         % them to the same value.
         %
     :- func eqvclass.divide_equivalence_classes(func(T) = U, eqvclass(T))
         = eqvclass(T).

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


File: mercury_library.info,  Node: erlang_builtin,  Next: exception,  Prev: eqvclass,  Up: Top

24 erlang_builtin
*****************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2007 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: erlang_builtin.m.
     % Main author: wangp.
     % Stability: low.
     %
     % This file is intended to hold things related to Erlang for the Erlang grade.
     % In non-Erlang grades this file should do nothing.
     %
     % Currently it contains a server that is started at program initialisation
     % to emulate global variables.  Lookups and updates of global mutables work by
     % sending and receiving messages to this server.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module erlang_builtin.
     :- interface.

     % This module exports nothing yet for public consumption; all exports
     % are via foreign_export.

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


File: mercury_library.info,  Node: exception,  Next: float,  Prev: erlang_builtin,  Up: Top

25 exception
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1997-2008, 2010-2011 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 module 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 foreign_export' throws an exception which is not caught within that
     % procedure, then you will get undefined behaviour.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module exception.
     :- interface.

     :- import_module io.
     :- import_module list.
     :- import_module maybe.
     :- import_module store.
     :- import_module univ.

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

         % Exceptions of this type are used by many parts of the Mercury
         % implementation to indicate an internal error.
         %
     :- type software_error
         --->    software_error(string).

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

     % The following type and inst 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, MaybeException, Solutions):
         %
         % Operational semantics:
         %   Try to find all solutions to Goal(S), using backtracking.
         %   Collect the solutions found in Solutions, until the goal
         %   either throws an exception or fails.  If it throws an
         %   exception E then MaybeException = yes(E), otherwise
         %   MaybeException = no.
         %
         % Declaratively it is equivalent to:
         %   all [S] (list.member(S, Solutions) => Goal(S)),
         %   (
         %       MaybeException = yes(_)
         %   ;
         %       MaybeException = no,
         %       all [S] (Goal(S) => list.member(S, Solutions))
         %   ).
         %
     :- pred try_all(pred(T), maybe(univ), list(T)).
     :- mode try_all(pred(out) is det,     out, out(nil_or_singleton_list))
         is cc_multi.
     :- mode try_all(pred(out) is semidet, out, out(nil_or_singleton_list))
         is cc_multi.
     :- mode try_all(pred(out) is multi,   out, out) is cc_multi.
     :- mode try_all(pred(out) is nondet,  out, out) is cc_multi.

     :- inst [] ---> [].
     :- inst nil_or_singleton_list ---> [] ; [ground].

         % incremental_try_all(Goal, AccumulatorPred, Acc0, Acc):
         %
         % Declaratively it is equivalent to:
         %   try_all(Goal, MaybeException, Solutions),
         %   list.map(wrap_success, Solutions, Results),
         %   list.foldl(AccumulatorPred, Results, Acc0, Acc1),
         %   (
         %       MaybeException = no,
         %       Acc = Acc1
         %   ;
         %       MaybeException = yes(Exception),
         %       AccumulatorPred(exception(Exception), Acc1, Acc)
         %   )
         %
         % where (wrap_success(S, R) <=> R = succeeded(S)).
         %
         % Operationally, however, incremental_try_all/5 will call
         % AccumulatorPred for each solution as it is obtained, rather than
         % first building a list of the solutions.
         %
     :- 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.

         % throw_if_near_stack_limits checks if the program is near
         % the limits of the Mercury stacks, and throws an exception
         % (near_stack_limits) if this is the case.
         %
         % This predicate works only in low level C grades; in other grades,
         % it never throws an exception.
         %
         % The predicate is impure instead of semipure because its effect
         % depends not only on the execution of other impure predicates,
         % but all calls.
         %
     :- type near_stack_limits
         --->    near_stack_limits.

     :- impure pred throw_if_near_stack_limits is det.

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


File: mercury_library.info,  Node: float,  Next: gc,  Prev: exception,  Up: Top

26 float
********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1994-1998,2001-2008,2010 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.
     %
     % Floats are double precision, except in .spf grades where they
     % are single precision.
     %
     % 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.

     :- import_module pretty_printer.

     %--------------------------------------------------%
     %
     % Arithmetic functions
     %

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

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

     	% multiplication
     	%
     :- func (float::in) * (float::in) = (float::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::in) / (float::in) = (float::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::in, float::in) = (float::uo) is det.

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

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

     %--------------------------------------------------%
     %
     % Comparison predicates
     %

     	% less than, greater than, less than or equal, greater than or equal.
     	%
     :- pred (float::in)  < (float::in) is semidet.
     :- pred (float::in) =< (float::in) is semidet.
     :- pred (float::in) >= (float::in) is semidet.
     :- pred (float::in) >  (float::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.

         % Convert a float to a pretty_printer.doc for formatting.
         %
     :- func float.float_to_doc(float) = doc.

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


File: mercury_library.info,  Node: gc,  Next: getopt_io,  Prev: float,  Up: Top

27 gc
*****

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1999,2001-2007 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.

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


File: mercury_library.info,  Node: getopt_io,  Next: getopt,  Prev: gc,  Up: Top

28 getopt_io
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 2005-2007, 2011 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_io.m
     % Authors: fjh, zs
     % Stability: medium
     %
     % This module exports the predicate getopt_io.process_options/6, 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
     %   - file_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.
     %
     % With the exception of file_special, 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.
     %
     % The file_special option type requires no handler, and is implemented
     % entirely by this module. It always takes a single argument, a file name.
     % Its handling always consists of reading the named file, converting its
     % contents into a sequence of words separated by white space, and interpreting
     % those words as options in the usual manner.
     %
     % Note that arguments following an option may be separated from the option by
     % either whitespace or an equals, `=', character, e.g. `--foo 3' and `--foo=3'
     % both specify the option `--foo' with the integer argument `3'.
     %
     % If the argument `--' is encountered on the command-line then option
     % processing will immediately terminate, without processing any remaining
     % options.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module getopt_io.
     :- interface.

     :- import_module bool.
     :- import_module char.
     :- import_module io.
     :- import_module list.
     :- import_module map.
     :- import_module maybe.
     :- import_module set.

     % getopt_io.process_options(OptionOps, Args, NonOptionArgs, Result)
     % getopt_io.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 multi.
     %   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_io.process_options(option_ops(OptionType)::in(option_ops),
         list(string)::in, list(string)::out, maybe_option_table(OptionType)::out,
         io::di, io::uo) is det.

     :- pred getopt_io.process_options(option_ops(OptionType)::in(option_ops),
         list(string)::in, list(string)::out, list(string)::out,
         maybe_option_table(OptionType)::out, io::di, io::uo) is det.

     % getopt_io.process_options_track(OptionOps, Args, OptionArgs,
     %       NonOptionArgs, OptionTable0, Result, OptionsSet)

     :- pred getopt_io.process_options_track(
         option_ops_track(OptionType)::in(option_ops_track),
         list(string)::in, list(string)::out, list(string)::out,
         option_table(OptionType)::in, maybe_option_table(OptionType)::out,
         set(OptionType)::out, io::di, io::uo) is det.

     :- pred init_option_table(
         pred(OptionType, option_data)::in(pred(out, out) is nondet),
         option_table(OptionType)::out) is det.

     :- pred init_option_table_multi(
         pred(OptionType, option_data)::in(pred(out, out) is multi),
         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))
                 )
         ;       option_ops_multi(
                     pred(char, OptionType),         % short_option
                     pred(string, OptionType),       % long_option
                     pred(OptionType, option_data)   % option_default
                 )
         ;       option_ops_multi(
                     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))
                 ).

     :- type option_ops_track(OptionType)
         --->    option_ops_track(
                     pred(char, OptionType),         % short_option
                     pred(string, OptionType),       % long_option
                     pred(OptionType, special_data,  % special option handler
                         option_table(OptionType),
                         maybe_option_table(OptionType),
                         set(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_multi(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(out, out) is multi                 % 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
             )
         ;   option_ops_multi(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(out, out) is multi,                % option_default
                 pred(in, in, in, out) is semidet        % special handler
             )
         )).

     :- inst option_ops_track ==
         bound((
             option_ops_track(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(in, in, in, out, 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
         ;       file_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_io.lookup_bool_option(option_table(Option)::in, Option::in,
         bool::out) is det.
     :- func getopt_io.lookup_bool_option(option_table(Option), Option) = bool.

     :- pred getopt_io.lookup_int_option(option_table(Option)::in, Option::in,
         int::out) is det.
     :- func getopt_io.lookup_int_option(option_table(Option), Option) = int.

     :- pred getopt_io.lookup_string_option(option_table(Option)::in, Option::in,
         string::out) is det.
     :- func getopt_io.lookup_string_option(option_table(Option), Option) = string.

     :- pred getopt_io.lookup_maybe_int_option(option_table(Option)::in, Option::in,
         maybe(int)::out) is det.
     :- func getopt_io.lookup_maybe_int_option(option_table(Option), Option) =
         maybe(int).

     :- pred getopt_io.lookup_maybe_string_option(option_table(Option)::in,
         Option::in, maybe(string)::out) is det.
     :- func getopt_io.lookup_maybe_string_option(option_table(Option), Option) =
         maybe(string).

     :- pred getopt_io.lookup_accumulating_option(option_table(Option)::in,
         Option::in, list(string)::out) is det.
     :- func getopt_io.lookup_accumulating_option(option_table(Option), Option) =
         list(string).

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


File: mercury_library.info,  Node: getopt,  Next: graph,  Prev: getopt_io,  Up: Top

29 getopt
*********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1994-1999,2001-2007, 2011 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
     %
     % A further special option, file_special, is supported only by the getopt_io
     % module, because it requires process_options to take a pair of I/O state
     % arguments.
     %
     % 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.
     %
     % Note that arguments following an option may be separated from the option by
     % either whitespace or an equals, `=', character, e.g. `--foo 3' and `--foo=3'
     % both specify the option `--foo' with the integer argument `3'.
     %
     % If the argument `--' is encountered on the command-line then option
     % processing will immediately terminate, without processing any remaining
     % options.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module getopt.
     :- interface.

     :- import_module bool.
     :- import_module char.
     :- import_module list.
     :- import_module map.
     :- import_module maybe.
     :- import_module set.

     % 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 multi.
     %   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.

     % getopt.process_options_track(OptionOps, Args, OptionArgs,
     %       NonOptionArgs, OptionTable0, Result, OptionsSet)

     :- pred getopt.process_options_track(
         option_ops_track(OptionType)::in(option_ops_track),
         list(string)::in, list(string)::out, list(string)::out,
         option_table(OptionType)::in, maybe_option_table(OptionType)::out,
         set(OptionType)::out) is det.

     :- pred init_option_table(
         pred(OptionType, option_data)::in(pred(out, out) is nondet),
         option_table(OptionType)::out) is det.

     :- pred init_option_table_multi(
         pred(OptionType, option_data)::in(pred(out, out) is multi),
         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))
                 )
         ;       option_ops_multi(
                     pred(char, OptionType),         % short_option
                     pred(string, OptionType),       % long_option
                     pred(OptionType, option_data)   % option_default
                 )
         ;       option_ops_multi(
                     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))
                 ).

     :- type option_ops_track(OptionType)
         --->    option_ops_track(
                     pred(char, OptionType),         % short_option
                     pred(string, OptionType),       % long_option
                     pred(OptionType, special_data,  % special option handler
                         option_table(OptionType),
                         maybe_option_table(OptionType),
                         set(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_multi(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(out, out) is multi                 % 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
             )
         ;   option_ops_multi(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(out, out) is multi,                % option_default
                 pred(in, in, in, out) is semidet        % special handler
             )
         )).

     :- inst option_ops_track ==
         bound((
             option_ops_track(
                 pred(in, out) is semidet,               % short_option
                 pred(in, out) is semidet,               % long_option
                 pred(in, in, in, out, 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)::in, Option::in,
         bool::out) is det.
     :- func getopt.lookup_bool_option(option_table(Option), Option) = bool.

     :- pred getopt.lookup_int_option(option_table(Option)::in, Option::in,
         int::out) is det.
     :- func getopt.lookup_int_option(option_table(Option), Option) = int.

     :- pred getopt.lookup_string_option(option_table(Option)::in, Option::in,
         string::out) is det.
     :- func getopt.lookup_string_option(option_table(Option), Option) = string.

     :- pred getopt.lookup_maybe_int_option(option_table(Option)::in, Option::in,
         maybe(int)::out) is det.
     :- func getopt.lookup_maybe_int_option(option_table(Option), Option) =
         maybe(int).

     :- pred getopt.lookup_maybe_string_option(option_table(Option)::in,
         Option::in, maybe(string)::out) is det.
     :- func getopt.lookup_maybe_string_option(option_table(Option), Option) =
         maybe(string).

     :- pred getopt.lookup_accumulating_option(option_table(Option)::in,
         Option::in, list(string)::out) is det.
     :- func getopt.lookup_accumulating_option(option_table(Option), Option) =
         list(string).

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


File: mercury_library.info,  Node: graph,  Next: group,  Prev: getopt,  Up: Top

30 graph
********

     %--------------------------------------------------%
     % THIS FILE IS NO LONGER USED.
     %--------------------------------------------------%


File: mercury_library.info,  Node: group,  Next: hash_table,  Prev: graph,  Up: Top

31 group
********

     %--------------------------------------------------%
     % THIS FILE IS NO LONGER USED.
     %--------------------------------------------------%


File: mercury_library.info,  Node: hash_table,  Next: injection,  Prev: group,  Up: Top

32 hash_table
*************

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2001, 2003-2006, 2010-2011 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, wangp.
     % Stability: low.
     %
     % Hash table implementation.
     %
     % This implementation requires the user to supply a predicate that
     % will compute a hash value for any given key.
     %
     % Default 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 array.
     :- import_module assoc_list.
     :- import_module 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, hash_pred, 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) ).
     :- inst hash_pred    == ( pred(in, out) is det ).

         % init(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 a hash for a given key.
         % N must be greater than 0.
         % MaxOccupancy must be in (0.0, 1.0).
         %
         % XXX Values too close to the limits may cause bad things
         % to happen.
         %
     :- func init(hash_pred(K), int, float) = hash_table(K, V).
     :- mode init(in(hash_pred), in, in) = hash_table_uo is det.

         % A synonym for the above.
         %
     :- pragma obsolete(new/3).
     :- func new(hash_pred(K), int, float) = hash_table(K, V).
     :- mode new(in(hash_pred), in, in) = hash_table_uo is det.

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

         % A synonym for the above.
         %
     :- pragma obsolete(new_default/1).
     :- 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_hash(int::in, int::out) is det.
     :- pred string_hash(string::in, int::out) is det.
     :- pred char_hash(char::in, int::out) is det.
     :- pred float_hash(float::in, int::out) is det.
     :- pred generic_hash(T::in, int::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.
         % A predicate version is also provided.
         %
     :- func set(hash_table(K, V), K, V) = hash_table(K, V).
     :- mode set(hash_table_di, in, in) = hash_table_uo is det.

     :- pred set(K::in, V::in,
         hash_table(K, V)::hash_table_di, hash_table(K, V)::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.  A predicate version is also provided.
         %
     :- 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.

     :- pred det_insert(K::in, V::in,
         hash_table(K, V)::hash_table_di, hash_table(K, V)::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.  A predicate version is also provided.
         %
     :- 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.

     :- pred det_update(K::in, V::in,
         hash_table(K, V)::hash_table_di, hash_table(K, V)::hash_table_uo) is det.

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

     :- pred delete(K::in,
         hash_table(K, V)::hash_table_di, hash_table(K, V)::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.

         % Convert an association list into a hash table.
         %
     :- func from_assoc_list(hash_pred(K)::in(hash_pred), assoc_list(K, V)::in) =
         (hash_table(K, V)::hash_table_uo) 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.

         % Fold a predicate over the key-value bindings in a hash table.
         %
     :- pred fold(pred(K, V, T, T), hash_table(K, V), T, T).
     :- mode fold(in(pred(in, in, in, out) is det), hash_table_ui,
         in, out) is det.
     :- mode fold(in(pred(in, in, mdi, muo) is det), hash_table_ui,
         mdi, muo) is det.
     :- mode fold(in(pred(in, in, di, uo) is det), hash_table_ui,
         di, uo) is det.
     :- mode fold(in(pred(in, in, in, out) is semidet), hash_table_ui,
         in, out) is semidet.
     :- mode fold(in(pred(in, in, mdi, muo) is semidet), hash_table_ui,
         mdi, muo) is semidet.
     :- mode fold(in(pred(in, in, di, uo) is semidet), hash_table_ui,
         di, uo) is semidet.

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


File: mercury_library.info,  Node: injection,  Next: integer,  Prev: hash_table,  Up: Top

33 injection
************

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 2005-2006, 2010-2011 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: injection.m.
     % Author: mark.
     % Stability: low.
     %
     % This module provides the `injection' ADT.  An injection is like a `map'
     % (see map.m) but it allows efficient reverse lookups, similarly to `bimap'.
     % This time efficiency comes at the expense of using twice as much space
     % or more.  The difference between an injection and a bimap is that there
     % can be values in the range of the injection that are not returned for any
     % key, but for which a reverse lookup will still return a valid key.
     %
     % The invariants on this data structure, which are enforced by this module,
     % are as follows:
     %
     % 1) For any key K, if a forward lookup succeeds with value V then a reverse
     % lookup of value V will succeed with key K.
     %
     % 2) For any value V, if a reverse lookup succeeds with key K then a forward
     % lookup of key K will succeed with some value (not necessarily V).
     %
     %--------------------------------------------------%
     %--------------------------------------------------%

     :- module injection.
     :- interface.

     :- import_module assoc_list.
     :- import_module list.
     :- import_module map.

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

     :- type injection(K, V).

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

         % Initialize an empty injection.
         %
     :- func injection.init = injection(K, V).
     :- pred injection.init(injection(K, V)::out) is det.

         % Intialise an injection wit the given key-value pair.
         %
     :- func injection.singleton(K, V) = injection(K, V).

         % Check whether an injection is empty.
         %
     :- pred injection.is_empty(injection(K, V)::in) is semidet.

         % Search the injection for the value corresponding to a given key.
         %
     :- func injection.forward_search(injection(K, V), K) = V is semidet.
     :- pred injection.forward_search(injection(K, V)::in, K::in, V::out)
         is semidet.

         % Search the injection for the key corresponding to a given value.
         %
     :- func injection.reverse_search(injection(K, V), V) = K is semidet.
     :- pred injection.reverse_search(injection(K, V)::in, K::out, V::in)
         is semidet.

         % Combined forward/reverse search.
         % (Declaratively equivalent to reverse_search.)
         %
     :- pred injection.search(injection(K, V), K, V).
     :- mode injection.search(in, in, out) is cc_nondet.
     :- mode injection.search(in, out, in) is semidet.

         % Look up the value for a given key, but throw an exception if it
         % is not present.
         %
     :- func injection.lookup(injection(K, V), K) = V.
     :- pred injection.lookup(injection(K, V)::in, K::in, V::out) is det.

         % Look up the key for a given value, but throw an exception if it
         % is not present.
         %
     :- func injection.reverse_lookup(injection(K, V), V) = K.
     :- pred injection.reverse_lookup(injection(K, V)::in, K::out, V::in) is det.

         % Return the list of all keys in the injection.
         %
     :- func injection.keys(injection(K, V)) = list(K).
     :- pred injection.keys(injection(K, V)::in, list(K)::out) is det.

         % Return the list of all values in the injection.
         %
     :- func injection.values(injection(K, V)) = list(V).
     :- pred injection.values(injection(K, V)::in, list(V)::out) is det.

         % Succeeds if the injection contains the given key.
         %
     :- pred injection.contains_key(injection(K, V)::in, K::in) is semidet.

         % Succeeds if the injection contains the given value.
         %
     :- pred injection.contains_value(injection(K, V)::in, V::in) is semidet.

         % Insert a new key-value pair into the injection.  Fails if either
         % the key or value already exists.
         %
     :- func injection.insert(injection(K, V), K, V) = injection(K, V) is semidet.
     :- pred injection.insert(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is semidet.

         % As above but throws an exception if the key or the value already
         % exists.
         %
     :- func injection.det_insert(injection(K, V), K, V) = injection(K, V).
     :- pred injection.det_insert(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is det.

         % Update the value associated with a given key.  Fails if the key
         % does not already exist, or if the value is already associated
         % with a key.
         %
     :- func injection.update(injection(K, V), K, V) = injection(K, V) is semidet.
     :- pred injection.update(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is semidet.

         % As above, but throws an exception if the key does not already exist,
         % or if the value is already associated with a key.
         %
     :- func injection.det_update(injection(K, V), K, V) = injection(K, V).
     :- pred injection.det_update(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is det.

         % Sets the value associated with a given key, regardless of whether
         % the key exists already or not.  Fails if the value is already
         % associated with a key that is different from the given key.
         %
     :- func injection.set(injection(K, V), K, V) = injection(K, V) is semidet.
     :- pred injection.set(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is semidet.

         % As above, but throws an exception if the value is already associated
         % with a key that is different from the given key.
         %
     :- func injection.det_set(injection(K, V), K, V) = injection(K, V).
     :- pred injection.det_set(injection(K, V)::in, K::in, V::in,
         injection(K, V)::out) is det.

         % Insert key-value pairs from an assoc_list into the given injection.
         % Fails if any of the individual inserts would fail.
         %
     :- func injection.insert_from_assoc_list(assoc_list(K, V), injection(K, V)) =
         injection(K, V) is semidet.
     :- pred injection.insert_from_assoc_list(assoc_list(K, V)::in,
         injection(K, V)::in, injection(K, V)::out) is semidet.

         % As above, but throws an exception if any of the individual
         % inserts would fail.
         %
     :- func injection.det_insert_from_assoc_list(assoc_list(K, V),
         injection(K, V)) = injection(K, V).
     :- pred injection.det_insert_from_assoc_list(assoc_list(K, V)::in,
         injection(K, V)::in, injection(K, V)::out) is det.

         % Set key-value pairs from an assoc_list into the given injection.
         % Fails of any of the individual sets would fail.
         %
     :- func injection.set_from_assoc_list(assoc_list(K, V), injection(K, V)) =
         injection(K, V) is semidet.
     :- pred injection.set_from_assoc_list(assoc_list(K, V)::in,
         injection(K, V)::in, injection(K, V)::out) is semidet.

         % As above, but throws an exception if any of the individual sets
         % would fail.
         %
     :- func injection.det_set_from_assoc_list(assoc_list(K, V), injection(K, V)) =
         injection(K, V).
     :- pred injection.det_set_from_assoc_list(assoc_list(K, V)::in,
         injection(K, V)::in, injection(K, V)::out) is det.

         % Insert key-value pairs from corresponding lists into the given
         % injection.  Fails if any of the individual inserts would fail.
         % Throws an exception if the lists are not of equal length.
         %
     :- func injection.insert_from_corresponding_lists(list(K), list(V),
         injection(K, V)) = injection(K, V) is semidet.
     :- pred injection.insert_from_corresponding_lists(list(K)::in, list(V)::in,
         injection(K, V)::in, injection(K, V)::out) is semidet.

         % As above, but throws an exception if any of the individual
         % inserts would fail.
         %
     :- func injection.det_insert_from_corresponding_lists(list(K), list(V),
         injection(K, V)) = injection(K, V).
     :- pred injection.det_insert_from_corresponding_lists(list(K)::in, list(V)::in,
         injection(K, V)::in, injection(K, V)::out) is det.

         % Set key-value pairs from corresponding lists into the given
         % injection.  Fails of any of the individual sets would fail.
         % Throws an exception if the lists are not of equal length.
         %
     :- func injection.set_from_corresponding_lists(list(K), list(V),
         injection(K, V)) = injection(K, V) is semidet.
     :- pred injection.set_from_corresponding_lists(list(K)::in, list(V)::in,
         injection(K, V)::in, injection(K, V)::out) is semidet.

         % As above, but throws an exception if any of the individual sets
         % would fail.
         %
     :- func injection.det_set_from_corresponding_lists(list(K), list(V),
         injection(K, V)) = injection(K, V).
     :- pred injection.det_set_from_corresponding_lists(list(K)::in, list(V)::in,
         injection(K, V)::in, injection(K, V)::out) is det.

         % Delete a key from an injection.  Also deletes any values that
         % correspond to that key.  If the key is not present, leave the
         % injection unchanged.
         %
     :- func injection.delete_key(injection(K, V), K) = injection(K, V).
     :- pred injection.delete_key(K::in, injection(K, V)::in, injection(K, V)::out)
         is det.

         % Delete a value from an injection.  Throws an exception if there is
         % a key that maps to this value.  If the value is not present, leave
         % the injection unchanged.
         %
     :- func injection.delete_value(injection(K, V), V) = injection(K, V).
     :- pred injection.delete_value(V::in, injection(K, V)::in,
         injection(K, V)::out) is det.

         % Apply injection.delete_key to a list of keys.
         %
     :- func injection.delete_keys(injection(K, V), list(K)) = injection(K, V).
     :- pred injection.delete_keys(list(K)::in, injection(K, V)::in,
         injection(K, V)::out) is det.

         % Apply injection.delete_value to a list of values.
         %
     :- func injection.delete_values(injection(K, V), list(V)) = injection(K, V).
     :- pred injection.delete_values(list(V)::in, injection(K, V)::in,
         injection(K, V)::out) is det.

         % Merge the contents of the two injections.  Both sets of keys must
         % be disjoint, and both sets of values must be disjoint.
         %
     :- func injection.merge(injection(K, V), injection(K, V)) = injection(K, V).
     :- pred injection.merge(injection(K, V)::in, injection(K, V)::in,
         injection(K, V)::out) is det.

         % Merge the contents of the two injections.  For keys that occur in
         % both injections, map them to the value in the second argument.
         % Both sets of values must be disjoint.
         %
     :- func injection.overlay(injection(K, V), injection(K, V)) = injection(K, V).
     :- pred injection.overlay(injection(K, V)::in, injection(K, V)::in,
         injection(K, V)::out) is det.

         % Apply an injection to a list of keys.  Throws an exception if any
         % of the keys are not present.
         %
     :- func injection.apply_forward_map_to_list(injection(K, V), list(K)) =
         list(V).
     :- pred injection.apply_forward_map_to_list(injection(K, V)::in, list(K)::in,
         list(V)::out) is det.

         % Apply the inverse of an injection to a list of values.  Throws an
         % exception if any of the values are not present.
         %
     :- func injection.apply_reverse_map_to_list(injection(K, V), list(V)) =
         list(K).
     :- pred injection.apply_reverse_map_to_list(injection(K, V)::in, list(V)::in,
         list(K)::out) is det.

         % Apply a transformation to all the keys in the injection.  If two
         % distinct keys become equal under this transformation then the
         % value associated with the greater of these two keys is used in the
         % result.
         %
     :- func injection.map_keys(func(V, K) = L, injection(K, V)) = injection(L, V).
     :- pred injection.map_keys(pred(V, K, L)::in(pred(in, in, out) is det),
         injection(K, V)::in, injection(L, V)::out) is det.

         % Same as injection.map_keys, but deletes any keys for which the
         % transformation fails.
         %
     :- pred injection.filter_map_keys(
         pred(V, K, L)::in(pred(in, in, out) is semidet),
         injection(K, V)::in, injection(L, V)::out) is det.

         % Apply a transformation to all the values in the injection.  If two
         % distinct values become equal under this transformation then the
         % reverse search of these two values in the original map must lead
         % to the same key.  If it doesn't, then throw an exception.
         %
     :- func injection.map_values(func(K, V) = W, injection(K, V)) =
         injection(K, W).
     :- pred injection.map_values(pred(K, V, W)::in(pred(in, in, out) is det),
         injection(K, V)::in, injection(K, W)::out) is det.

         % Extract the forward map from an injection.
         %
     :- func injection.forward_map(injection(K, V)) = map(K, V).
     :- pred injection.forward_map(injection(K, V)::in, map(K, V)::out) is det.

         % Extract the reverse map from an injection.
         %
     :- func injection.reverse_map(injection(K, V)) = map(V, K).
     :- pred injection.reverse_map(injection(K, V)::in, map(V, K)::out) is det.

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


File: mercury_library.info,  Node: integer,  Next: int,  Prev: injection,  Up: Top

34 integer
**********

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
     %--------------------------------------------------%
     % Copyright (C) 1997-2000, 2003-2007, 2011 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, Dan Hazel <odin@svrc.uq.edu.au>.
     % Stability: high.
     %
     % 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.

     :- 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.det_from_string(string) = integer.

         % Convert a string in the specified base (2-36) to an integer.
         % The string must contain one or more digits in the specified base,
         % optionally preceded by a plus or minus sign.  For bases > 10, digits
         % 10 to 35 are represented by the letters A-Z or a-z.  If the string
         % does not match this syntax then the function fails.
         %
     :- func integer.from_base_string(int, string) = integer is semidet.

         % As above but throws an exception rather than failing.
         %
     :- func integer.det_from_base_string(int, string) = integer.

     :- 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.

         % divide_with_rem(X, Y, Q, R) where Q = X // Y and R = X rem Y
         % where both answers are calculated at the same time.
         %
     :- pred divide_with_rem(integer::in, integer::in,
         integer::out, integer::out) is det.

     :- 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.

     :- func integer.pow(integer, integer) = integer.

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

     :- func integer.zero = integer.

     :- func integer.one = integer.

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

