mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
396 lines
13 KiB
Mathematica
396 lines
13 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2002-2011 The University of Melbourne.
|
|
% Copyright (C) 2020-2023, 2025 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.index_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
|
|
% target_ids in those sets, so we keep two maps
|
|
%
|
|
% module_name <-> module_index, and
|
|
% target_id <-> target_id_index
|
|
%
|
|
% in the make_info structure, and work with sets of indices instead.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module make.index_set.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.file_util.
|
|
:- 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.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type module_index.
|
|
:- instance uenum(module_index).
|
|
|
|
:- type target_id_index.
|
|
:- instance uenum(target_id_index).
|
|
|
|
:- type module_index_set == index_set(module_index).
|
|
:- type target_id_index_set == index_set(target_id_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, module_index_set::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,
|
|
module_index_set::in, set(module_name)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Convert a target id to a target_id_index.
|
|
%
|
|
:- pred target_id_to_index(target_id_module_index::in, target_id_index::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
% Convert a list of target ids, or raw filenames, to a target_id_index set.
|
|
%
|
|
:- pred target_ids_to_index_set(list(target_id)::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
:- pred file_names_to_index_set(list(file_name)::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
% Convert a target_id_index set to a target_id set.
|
|
%
|
|
:- pred target_id_index_set_to_plain_set(make_info::in,
|
|
target_id_index_set::in, set(target_id)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type index_set(T) == sparse_bitset(T).
|
|
|
|
%---------------------%
|
|
%
|
|
% Creation, insertion, deletion.
|
|
%
|
|
|
|
:- func index_set_init = index_set(T).
|
|
|
|
:- pred index_set_insert(T::in, index_set(T)::in, index_set(T)::out)
|
|
is det <= uenum(T).
|
|
:- pred index_set_delete(T::in, index_set(T)::in, index_set(T)::out)
|
|
is det <= uenum(T).
|
|
|
|
%---------------------%
|
|
%
|
|
% Membership test.
|
|
%
|
|
|
|
:- pred index_set_member(T::in, index_set(T)::in) is semidet <= uenum(T).
|
|
|
|
%---------------------%
|
|
%
|
|
% Union and difference.
|
|
%
|
|
|
|
:- func index_set_union(index_set(T), index_set(T)) = index_set(T).
|
|
:- pred index_set_union(index_set(T)::in, index_set(T)::in, index_set(T)::out)
|
|
is det.
|
|
|
|
:- func index_set_union_list(list(index_set(T))) = index_set(T).
|
|
|
|
:- func index_set_difference(index_set(T), index_set(T)) = index_set(T).
|
|
|
|
%---------------------%
|
|
%
|
|
% Conversion from and to lists.
|
|
%
|
|
|
|
:- func list_to_index_set(list(T)) = index_set(T) <= uenum(T).
|
|
:- pred list_to_index_set(list(T)::in, index_set(T)::out) is det <= uenum(T).
|
|
|
|
:- func index_set_to_sorted_list(index_set(T)) = list(T) <= uenum(T).
|
|
|
|
%---------------------%
|
|
%
|
|
% Folds.
|
|
%
|
|
|
|
:- pred index_set_foldl(
|
|
pred(T, A, A)::in(pred(in, in, out) is det),
|
|
index_set(T)::in, A::in, A::out) is det <= uenum(T).
|
|
|
|
:- pred index_set_foldl2(
|
|
pred(T, A, A, B, B)::in(pred(in, in, out, in, out) is det),
|
|
index_set(T)::in, A::in, A::out, B::in, B::out) is det <= uenum(T).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int.
|
|
:- import_module uint.
|
|
:- import_module version_array.
|
|
:- import_module version_hash_table.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Bitset index types.
|
|
%
|
|
|
|
:- type module_index
|
|
---> module_index(uint).
|
|
|
|
:- instance uenum(module_index) where [
|
|
to_uint(module_index(U)) = U,
|
|
from_uint(U, module_index(U))
|
|
].
|
|
|
|
:- type target_id_index
|
|
---> target_id_index(uint).
|
|
|
|
:- instance uenum(target_id_index) where [
|
|
to_uint(target_id_index(U)) = U,
|
|
from_uint(U, target_id_index(U))
|
|
].
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
module_name_to_index(ModuleName, Index, !Info) :-
|
|
Map0 = make_info_get_module_index_map(!.Info),
|
|
Map0 = module_index_map(ForwardMap0, _ReverseMap0, _USize0),
|
|
( if version_hash_table.search(ForwardMap0, ModuleName, Index0) then
|
|
Index = Index0
|
|
else
|
|
Map0 = module_index_map(_ForwardMap0, ReverseMap0, USize0),
|
|
Slot = USize0,
|
|
Index = module_index(USize0),
|
|
USize = USize0 + 1u,
|
|
version_hash_table.det_insert(ModuleName, Index,
|
|
ForwardMap0, ForwardMap),
|
|
RevSize0 = version_array.size(ReverseMap0),
|
|
( if uint.cast_to_int(USize) > RevSize0 then
|
|
RevSize = increase_array_size(RevSize0),
|
|
version_array.resize(RevSize, ModuleName, ReverseMap0, ReverseMap)
|
|
else
|
|
version_array.set(uint.cast_to_int(Slot), ModuleName,
|
|
ReverseMap0, ReverseMap)
|
|
),
|
|
Map = module_index_map(ForwardMap, ReverseMap, USize),
|
|
make_info_set_module_index_map(Map, !Info)
|
|
).
|
|
|
|
:- 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_loop(ModuleNames,
|
|
index_set_init, IndexSet, !Info).
|
|
|
|
:- pred module_names_to_index_set_loop(list(module_name)::in,
|
|
module_index_set::in, module_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
module_names_to_index_set_loop([], !IndexSet, !Info).
|
|
module_names_to_index_set_loop([ModuleName | ModuleNames], !Set, !Info) :-
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
index_set_insert(ModuleIndex, !Set),
|
|
module_names_to_index_set_loop(ModuleNames, !Set, !Info).
|
|
|
|
%---------------------%
|
|
|
|
module_index_to_name(Info, Index, ModuleName) :-
|
|
make_info_get_module_index_map(Info) =
|
|
module_index_map(_ForwardMap, ReverseMap, _Size),
|
|
Index = module_index(U),
|
|
ModuleName = version_array.lookup(ReverseMap, uint.cast_to_int(U)).
|
|
|
|
%---------------------%
|
|
|
|
module_index_set_to_plain_set(Info, ModuleIndices, Modules) :-
|
|
index_set_foldl(acc_module_index_set_to_plain_set(Info), ModuleIndices,
|
|
set.init, Modules).
|
|
|
|
:- pred acc_module_index_set_to_plain_set(make_info::in, module_index::in,
|
|
set(module_name)::in, set(module_name)::out) is det.
|
|
|
|
acc_module_index_set_to_plain_set(Info, ModuleIndex, !Set) :-
|
|
module_index_to_name(Info, ModuleIndex, ModuleName),
|
|
set.insert(ModuleName, !Set).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
target_id_to_index(TargetId, Index, !Info) :-
|
|
Map0 = make_info_get_target_id_index_map(!.Info),
|
|
Map0 = target_id_index_map(ForwardMap0, _ReverseMap0, _USize0),
|
|
( if version_hash_table.search(ForwardMap0, TargetId, Index0) then
|
|
Index = Index0
|
|
else
|
|
Map0 = target_id_index_map(_ForwardMap0, ReverseMap0, USize0),
|
|
Slot = USize0,
|
|
Index = target_id_index(USize0),
|
|
USize = USize0 + 1u,
|
|
version_hash_table.det_insert(TargetId, Index,
|
|
ForwardMap0, ForwardMap),
|
|
RevSize0 = version_array.size(ReverseMap0),
|
|
( if uint.cast_to_int(USize) > RevSize0 then
|
|
RevSize = increase_array_size(RevSize0),
|
|
version_array.resize(RevSize, TargetId, ReverseMap0, ReverseMap)
|
|
else
|
|
version_array.set(uint.cast_to_int(Slot), TargetId,
|
|
ReverseMap0, ReverseMap)
|
|
),
|
|
Map = target_id_index_map(ForwardMap, ReverseMap, USize),
|
|
make_info_set_target_id_index_map(Map, !Info)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
target_ids_to_index_set(TargetIds, TargetIdIndexSet, !Info) :-
|
|
list.foldl2(acc_target_ids_to_index_set, TargetIds,
|
|
index_set_init, TargetIdIndexSet, !Info).
|
|
|
|
:- pred acc_target_ids_to_index_set(target_id::in,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
acc_target_ids_to_index_set(TargetId, !TargetIdIndexSet, !Info) :-
|
|
(
|
|
TargetId = merc_target(target_file(ModuleName, TargetType)),
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
TargetIdMI = timi_merc(ModuleIndex, TargetType)
|
|
;
|
|
TargetId = non_merc_target(FileName),
|
|
TargetIdMI = timi_non_merc(FileName)
|
|
),
|
|
target_id_to_index(TargetIdMI, TargetIdIndex, !Info),
|
|
index_set_insert(TargetIdIndex, !TargetIdIndexSet).
|
|
|
|
%---------------------%
|
|
|
|
file_names_to_index_set(FileNames, TargetIdIndexSet, !Info) :-
|
|
list.foldl2(acc_file_names_to_index_set, FileNames,
|
|
index_set_init, TargetIdIndexSet, !Info).
|
|
|
|
:- pred acc_file_names_to_index_set(file_name::in,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
acc_file_names_to_index_set(FileName, !TargetIdIndexSet, !Info) :-
|
|
TargetId = timi_non_merc(FileName),
|
|
target_id_to_index(TargetId, TargetIdIndex, !Info),
|
|
index_set_insert(TargetIdIndex, !TargetIdIndexSet).
|
|
|
|
%---------------------%
|
|
|
|
target_id_index_set_to_plain_set(Info, TargetIdIndexes, TargetIds) :-
|
|
index_set_foldl(acc_target_id_index_set_to_plain_set(Info),
|
|
TargetIdIndexes, [], TargetIdsList),
|
|
TargetIds = set.list_to_set(TargetIdsList).
|
|
|
|
:- pred acc_target_id_index_set_to_plain_set(make_info::in,
|
|
target_id_index::in, list(target_id)::in, list(target_id)::out) is det.
|
|
|
|
acc_target_id_index_set_to_plain_set(Info, TargetIndex, !TargetIds) :-
|
|
index_to_target_id(Info, TargetIndex, TargetId),
|
|
!:TargetIds = [TargetId | !.TargetIds].
|
|
|
|
:- pred index_to_target_id(make_info::in, target_id_index::in,
|
|
target_id::out) is det.
|
|
|
|
index_to_target_id(Info, Index, TargetId) :-
|
|
make_info_get_target_id_index_map(Info) =
|
|
target_id_index_map(_ForwardMap, ReverseMap, _Size),
|
|
Index = target_id_index(U),
|
|
version_array.lookup(ReverseMap, uint.cast_to_int(U), TargetId0),
|
|
(
|
|
TargetId0 = timi_merc(ModuleIndex, FileType),
|
|
module_index_to_name(Info, ModuleIndex, ModuleName),
|
|
TargetId = merc_target(target_file(ModuleName, FileType))
|
|
;
|
|
TargetId0 = timi_non_merc(FileName),
|
|
TargetId = non_merc_target(FileName)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Operations on index_sets.
|
|
%
|
|
|
|
index_set_init = sparse_bitset.init.
|
|
|
|
%---------------------%
|
|
|
|
index_set_insert(X, !Set) :-
|
|
sparse_bitset.insert(X, !Set).
|
|
|
|
index_set_delete(X, !Set) :-
|
|
sparse_bitset.delete(X, !Set).
|
|
|
|
%---------------------%
|
|
|
|
index_set_member(Item, Set) :-
|
|
sparse_bitset.member(Item, Set).
|
|
|
|
%---------------------%
|
|
|
|
index_set_union(SetA, SetB) = Set :-
|
|
Set = sparse_bitset.union(SetA, SetB).
|
|
|
|
index_set_union(SetA, SetB, Set) :-
|
|
sparse_bitset.union(SetA, SetB, Set).
|
|
|
|
index_set_union_list(Sets) = Set :-
|
|
Set = sparse_bitset.union_list(Sets).
|
|
|
|
index_set_difference(SetA, SetB) = Set :-
|
|
Set = sparse_bitset.difference(SetA, SetB).
|
|
|
|
%---------------------%
|
|
|
|
list_to_index_set(List) = Set :-
|
|
sparse_bitset.list_to_set(List, Set).
|
|
|
|
list_to_index_set(List, Set) :-
|
|
sparse_bitset.list_to_set(List, Set).
|
|
|
|
index_set_to_sorted_list(Set) = SortedList :-
|
|
SortedList = sparse_bitset.to_sorted_list(Set).
|
|
|
|
%---------------------%
|
|
|
|
index_set_foldl(Pred, Set, !Acc1) :-
|
|
sparse_bitset.foldl(Pred, Set, !Acc1).
|
|
|
|
index_set_foldl2(Pred, Set, !Acc1, !Acc2) :-
|
|
sparse_bitset.foldl2(Pred, Set, !Acc1, !Acc2).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module make.index_set.
|
|
%---------------------------------------------------------------------------%
|