mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-17 10:23:46 +00:00
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.
272 lines
9.5 KiB
Mathematica
272 lines
9.5 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2002-2011 The University of Melbourne.
|
|
% Copyright (C) 2020-2022 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: make.deps_set.m.
|
|
%
|
|
% Dependency computation does a lot of unions so we use a set representation
|
|
% suited to that purpose, namely bitsets. We can't store module_names and
|
|
% dependency_files in those sets, so we keep two maps
|
|
%
|
|
% module_name <-> module_index, and
|
|
% dependency_file <-> dependency_file_index
|
|
%
|
|
% in the make_info structure, and work with sets of indices instead.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module make.deps_set.
|
|
:- interface.
|
|
|
|
:- import_module make.dependencies.
|
|
:- import_module make.make_info.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
|
|
:- import_module enum.
|
|
:- import_module list.
|
|
:- import_module set.
|
|
:- import_module sparse_bitset.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% sparse_bitset is faster than tree_bitset by my tests.
|
|
%
|
|
:- type deps_set(T) == sparse_bitset(T).
|
|
% :- type deps_set(T) == tree_bitset(T).
|
|
|
|
:- type module_index.
|
|
:- instance uenum(module_index).
|
|
|
|
:- type dependency_file_index.
|
|
:- instance uenum(dependency_file_index).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Convert a module_name to a module_index.
|
|
%
|
|
:- pred module_name_to_index(module_name::in, module_index::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
% Convert a list of module_names to a module_index set.
|
|
%
|
|
:- pred module_names_to_index_set(list(module_name)::in,
|
|
deps_set(module_index)::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
% Convert a module_index to a module_name.
|
|
%
|
|
:- pred module_index_to_name(make_info::in,
|
|
module_index::in, module_name::out) is det.
|
|
|
|
% Convert a module_index set to a module_name set.
|
|
%
|
|
:- pred module_index_set_to_plain_set(make_info::in,
|
|
deps_set(module_index)::in, set(module_name)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Convert a dependency file to a dependency_file_index.
|
|
%
|
|
:- pred dependency_file_to_index(dependency_file_with_module_index::in,
|
|
dependency_file_index::out, make_info::in, make_info::out) is det.
|
|
|
|
% Convert a list of dependency files to a dependency_file_index set.
|
|
%
|
|
:- pred dependency_files_to_index_set(list(dependency_file)::in,
|
|
deps_set(dependency_file_index)::out, make_info::in, make_info::out)
|
|
is det.
|
|
|
|
% Convert a dependency_file_index set to a dependency_file set.
|
|
%
|
|
:- pred dependency_file_index_set_to_plain_set(make_info::in,
|
|
deps_set(dependency_file_index)::in, set(dependency_file)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.
|
|
:- import_module parse_tree.
|
|
|
|
:- import_module int.
|
|
:- import_module maybe.
|
|
:- import_module uint.
|
|
:- import_module version_array.
|
|
:- import_module version_hash_table.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Bitset indices.
|
|
%
|
|
|
|
:- type module_index
|
|
---> module_index(uint).
|
|
|
|
:- instance uenum(module_index) where [
|
|
to_uint(module_index(U)) = U,
|
|
from_uint(U, module_index(U))
|
|
].
|
|
|
|
:- type dependency_file_index
|
|
---> dependency_file_index(uint).
|
|
|
|
:- instance uenum(dependency_file_index) where [
|
|
to_uint(dependency_file_index(U)) = U,
|
|
from_uint(U, dependency_file_index(U))
|
|
].
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
module_name_to_index(ModuleName, Index, !Info) :-
|
|
Map0 = !.Info ^ mki_module_index_map,
|
|
Map0 = module_index_map(Forward0, _Reverse0, _Size0),
|
|
( if version_hash_table.search(Forward0, ModuleName, Index0) then
|
|
Index = Index0
|
|
else
|
|
Map0 = module_index_map(_Forward0, Reverse0, USize0),
|
|
Slot = USize0,
|
|
Index = module_index(USize0),
|
|
USize = USize0 + 1u,
|
|
version_hash_table.det_insert(ModuleName, Index, Forward0, Forward),
|
|
TrueSize = version_array.size(Reverse0),
|
|
( if cast_to_int(USize) > TrueSize then
|
|
NewSize = increase_array_size(TrueSize),
|
|
version_array.resize(NewSize, ModuleName, Reverse0, Reverse)
|
|
else
|
|
version_array.set(cast_to_int(Slot), ModuleName, Reverse0, Reverse)
|
|
),
|
|
Map = module_index_map(Forward, Reverse, USize),
|
|
!Info ^ mki_module_index_map := Map
|
|
).
|
|
|
|
:- func increase_array_size(int) = int.
|
|
|
|
increase_array_size(N) = (if N = 0 then 1 else N * 2).
|
|
|
|
%---------------------%
|
|
|
|
module_names_to_index_set(ModuleNames, IndexSet, !Info) :-
|
|
module_names_to_index_set_2(ModuleNames,
|
|
sparse_bitset.init, IndexSet, !Info).
|
|
|
|
:- pred module_names_to_index_set_2(list(module_name)::in,
|
|
deps_set(module_index)::in, deps_set(module_index)::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
module_names_to_index_set_2([], !IndexSet, !Info).
|
|
module_names_to_index_set_2([ModuleName | ModuleNames], !Set, !Info) :-
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
sparse_bitset.insert(ModuleIndex, !Set),
|
|
module_names_to_index_set_2(ModuleNames, !Set, !Info).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
module_index_to_name(Info, Index, ModuleName) :-
|
|
Info ^ mki_module_index_map = module_index_map(_Forward, Reverse, _Size),
|
|
Index = module_index(I),
|
|
ModuleName = version_array.lookup(Reverse, cast_to_int(I)).
|
|
|
|
%---------------------%
|
|
|
|
module_index_set_to_plain_set(Info, ModuleIndices, Modules) :-
|
|
foldl(module_index_set_to_plain_set_2(Info), ModuleIndices,
|
|
set.init, Modules).
|
|
|
|
:- pred module_index_set_to_plain_set_2(make_info::in, module_index::in,
|
|
set(module_name)::in, set(module_name)::out) is det.
|
|
|
|
module_index_set_to_plain_set_2(Info, ModuleIndex, !Set) :-
|
|
module_index_to_name(Info, ModuleIndex, ModuleName),
|
|
set.insert(ModuleName, !Set).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
dependency_file_to_index(DepFile, Index, !Info) :-
|
|
Map0 = !.Info ^ mki_dep_file_index_map,
|
|
ForwardMap0 = Map0 ^ dfim_forward_map,
|
|
( if version_hash_table.search(ForwardMap0, DepFile, Index0) then
|
|
Index = Index0
|
|
else
|
|
Map0 = dependency_file_index_map(Forward0, Reverse0, USize0),
|
|
Slot = USize0,
|
|
Index = dependency_file_index(USize0),
|
|
USize = USize0 + 1u,
|
|
version_hash_table.det_insert(DepFile, Index, Forward0, Forward),
|
|
TrueSize = version_array.size(Reverse0),
|
|
( if cast_to_int(USize) > TrueSize then
|
|
NewSize = increase_array_size(TrueSize),
|
|
version_array.resize(NewSize, DepFile, Reverse0, Reverse)
|
|
else
|
|
version_array.set(cast_to_int(Slot), DepFile, Reverse0, Reverse)
|
|
),
|
|
Map = dependency_file_index_map(Forward, Reverse, USize),
|
|
!Info ^ mki_dep_file_index_map := Map
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
dependency_files_to_index_set(DepFiles, DepIndexSet, !Info) :-
|
|
list.foldl2(dependency_files_to_index_set_2, DepFiles,
|
|
init, DepIndexSet, !Info).
|
|
|
|
:- pred dependency_files_to_index_set_2(dependency_file::in,
|
|
deps_set(dependency_file_index)::in, deps_set(dependency_file_index)::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
dependency_files_to_index_set_2(DepFile0, !Set, !Info) :-
|
|
(
|
|
DepFile0 = dep_target(target_file(ModuleName, TargetType)),
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
DepFile = dfmi_target(ModuleIndex, TargetType)
|
|
;
|
|
DepFile0 = dep_file(FileName),
|
|
DepFile = dfmi_file(FileName)
|
|
),
|
|
dependency_file_to_index(DepFile, DepIndex, !Info),
|
|
insert(DepIndex, !Set).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred index_to_dependency_file(make_info::in, dependency_file_index::in,
|
|
dependency_file::out) is det.
|
|
|
|
index_to_dependency_file(Info, Index, DepFile) :-
|
|
Info ^ mki_dep_file_index_map =
|
|
dependency_file_index_map(_Forward, Reverse, _Size),
|
|
Index = dependency_file_index(I),
|
|
version_array.lookup(Reverse, cast_to_int(I), DepFile0),
|
|
(
|
|
DepFile0 = dfmi_target(ModuleIndex, FileType),
|
|
module_index_to_name(Info, ModuleIndex, ModuleName),
|
|
DepFile = dep_target(target_file(ModuleName, FileType))
|
|
;
|
|
DepFile0 = dfmi_file(FileName),
|
|
DepFile = dep_file(FileName)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
dependency_file_index_set_to_plain_set(Info, DepIndices, DepFiles) :-
|
|
foldl(dependency_file_index_set_to_plain_set_2(Info), DepIndices,
|
|
[], DepFilesList),
|
|
DepFiles = set.list_to_set(DepFilesList).
|
|
|
|
:- pred dependency_file_index_set_to_plain_set_2(make_info::in,
|
|
dependency_file_index::in,
|
|
list(dependency_file)::in, list(dependency_file)::out) is det.
|
|
|
|
dependency_file_index_set_to_plain_set_2(Info, DepIndex, List0, List) :-
|
|
index_to_dependency_file(Info, DepIndex, DepFile),
|
|
List = [DepFile | List0].
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module make.deps_set.
|
|
%---------------------------------------------------------------------------%
|