Files
mercury/library/enum.m
Zoltan Somogyi ec20b1ed0a Make sparse_bitset.m operate on uints.
NEWS:
    Mention all the user-visible changes below.

library/enum.m:
    Add the typeclass uenum, which is a version of the existing enum typeclass
    that maps items to uints, not ints. It also uses a semidet predicate,
    not a semidet function, to get back to the item from the uint.

library/sparse_bitset.m:
library/fat_sparse_bitset.m:
    Make these modules operate on uints, which means requiring the items
    in the sets to be instances of uenum, not enum.

    If a few places, improve loops by doing previously-repeated conversions
    of [u]ints into <offset, bit-to-set> pairs just once.

library/counter.m:
    Define ucounters, which allocate uints. Improve documentation.

library/digraph.m:
    Change digraph_keys from ints to uints, since we put them into
    sparse_bitsets.

library/int.m:
    Make int an instance of the uenum typeclass. This can help users
    who currently put ints into sparse_bitsets.

library/pprint.m:
    Prettyprint sparse_bitsets as lists of uints.

library/term.m:
    Make vars instances of uenum as well as enum.

library/uint.m:
    Make uint an instance of the uenum typeclass.

    Add the ubits_per_uint function, which allows some casts to be avoided.

compiler/make.deps_set.m:
    Change the indexes we put into sparse_bitsets from ints to uints.

compiler/make.make_info.m:
    Change the source of those indexes from ints to uints.

compiler/make.top_level.m:
compiler/make.util.m:
    Conform to the changes above.

compiler/pre_quantification.m:
    Change zones from ints to uints, since we put them into sparse_bitsets.

tests/hard_coded/int_uenum.{m,exp}:
tests/hard_coded/Mmakefile:
    Enable the new test case.

tests/valid/use_import_only_for_instance.m:
    Update this extract from library/digraph.m the same way as
    library/digraph.m itself.
2022-12-05 09:45:11 +11:00

88 lines
3.0 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2000, 2005-2006 The University of Melbourne.
% Copyright (C) 2014-2015, 2017-2018, 2022 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
%
% 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.
% A type T can be declared to be a member of the enum typeclass if
%
% - all values X of type T can be converted to an int N using
% the instance's to_int member function, with each distinct X
% being translated by to_int to a distinct N; and
%
% - for all values N of type int that are equal to to_int(X) for some X,
% from_int(N) = X.
%
% - for all values N of type int that are not equal to to_int(X) for any X,
% from_int(N) should fail.
%
% In mathematical notation, the following must hold:
%
% all [X] (X = from_int(to_int(X)))
% all [X, Y] (to_int(X) = to_int(Y)) => X = Y)
% all [N] (some [X] N = to_int(X) => from_int(N) = X)
% all [N] (not (some [X] N = to_int(X))) => from_int(N) fails
%
:- typeclass enum(T) where [
func to_int(T) = int,
func from_int(int) = T is semidet
].
% This is another version of the above typeclass, which maps
% values of type T to *unsigned* integers.
%
% The other difference is that the from_uint method is a semidet
% *predicate*, not a semidet *function*. This is because programmers
% are more likely to expect predicates to be able to fail than functions.
%
:- typeclass uenum(T) where [
func to_uint(T) = uint,
pred from_uint(uint::in, T::out) is semidet
].
% det_from_int(I) returns the result of from_int(I), but throws an
% exception if from_int fails.
%
:- func det_from_int(int) = T <= enum(T).
:- func det_from_uint(uint) = T <= uenum(T).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module require.
det_from_int(I) = X :-
( if X0 = from_int(I) then
X = X0
else
unexpected($pred, "from_int failed")
).
det_from_uint(U) = X :-
( if from_uint(U, X0) then
X = X0
else
unexpected($pred, "from_uint failed")
).
%---------------------------------------------------------------------------%
:- end_module enum.
%---------------------------------------------------------------------------%