mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-17 10:23:46 +00:00
... and start using their more descriptively-named synonyms.
In some cases, instead of getting and then reversing a list of sccs,
ask for the sccs in the needed order in the first place.
compiler/dependency_graph.m:
compiler/generate_dep_d_files.m:
compiler/make.program_target.m:
compiler/mlds_to_java_global.m:
compiler/mode_ordering.m:
compiler/rtti_to_mlds.m:
compiler/stratify.m:
As above.
compiler/prog_event.m:
As above.
Address an old and now-inaccurate XXX. When a synthesized attribute
depends on its value, either directly or through the values of other
synthesized attributes, include the names of the attributes involved
in the error message, instead of just saying that there is circular
dependency *somewhere* among the attributes.
tests/invalid/synth_attr_error.err_exp:
Expect the updated, more specific error messages.
tests/invalid/Mmakefile:
Enable the synth_attr_error test case, which wasn't enabled before
(though it does have an entry in Mercury.options.)
tests/invalid/invalid_event_spec:
tests/invalid/syntax_error_event_spec:
tests/invalid/synth_attr_error_spec:
Replace tabs with spaces.
140 lines
5.4 KiB
Mathematica
140 lines
5.4 KiB
Mathematica
%-----------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------%
|
|
% Copyright (C) 2017 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: dependency_graph.m.
|
|
%
|
|
% These are generic types and predicates for managing a dependency graph.
|
|
% hlds_dependency_graph.m uses it, and if we need an mlds_dependency_graph.m,
|
|
% that would use it too.
|
|
%
|
|
% A dependency_graph records which entities depend on which other entities.
|
|
% (For hlds_dependency_graph.m, the entities are HLDS procedures.)
|
|
% It is defined as a digraph R where the presence of an edge x -> y means that
|
|
% the definition of x depends on the definition of y.
|
|
%
|
|
% The reason why we build the dependency graph is because from it,
|
|
% we can compute the list of the SCCs (strongly-connected components)
|
|
% of this graph. This list of SCCs is the bottom_up_dependency_sccs, the other
|
|
% component in a dependency_graph itself.
|
|
%
|
|
%-----------------------------------------------------------------------%
|
|
|
|
:- module libs.dependency_graph.
|
|
:- interface.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module digraph.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module set.
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
% A dependency_info contains
|
|
%
|
|
% - a dependency_graph,
|
|
% - a list of the arcs in that graph, in which the same arc
|
|
% may appear more than once), and
|
|
% - a dependency_ordering.
|
|
%
|
|
% Calling make_dependency_info on a graph fills in the dependency_ordering.
|
|
%
|
|
:- type dependency_info(T).
|
|
|
|
:- type dependency_graph(T) == digraph(T).
|
|
:- type dependency_graph_key(T) == digraph_key(T).
|
|
:- type dependency_arcs(T) == assoc_list(digraph_key(T), digraph_key(T)).
|
|
:- type scc_map(T) == map(T, set(T)).
|
|
|
|
% A dependency ordering gives the list of SCCs of the analysed entities.
|
|
% (For hlds_dependency_graph.m, this will be all the predicates or all
|
|
% the procedure of the module being compiled.)
|
|
%
|
|
% The list is in ascending order: the lowest SCC is first,
|
|
% the highest SCC is last.
|
|
%
|
|
:- type bottom_up_dependency_sccs(T) == list(set(T)).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
:- func make_dependency_info(digraph(T), dependency_arcs(T))
|
|
= dependency_info(T).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
:- func dependency_info_get_graph(dependency_info(T))
|
|
= dependency_graph(T).
|
|
:- func dependency_info_get_arcs(dependency_info(T))
|
|
= dependency_arcs(T).
|
|
:- func dependency_info_get_bottom_up_sccs(dependency_info(T))
|
|
= bottom_up_dependency_sccs(T).
|
|
|
|
% This function does the same job as dependency_info_get_ordering,
|
|
% except that it condenses all the nodes into a single list.
|
|
% This is useful when the caller wants to process entities bottom up,
|
|
% but the SCC boundaries are not relevant.
|
|
%
|
|
:- func dependency_info_get_condensed_bottom_up_sccs(dependency_info(T))
|
|
= list(T).
|
|
|
|
% Build a map from each node to its SCC.
|
|
%
|
|
:- func dependency_info_make_scc_map(dependency_info(T)) = scc_map(T).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
:- type dependency_info(T)
|
|
---> dependency_info(
|
|
dep_graph :: dependency_graph(T),
|
|
dep_arcs :: dependency_arcs(T),
|
|
dep_bottom_up_sccs :: bottom_up_dependency_sccs(T)
|
|
).
|
|
|
|
make_dependency_info(Graph, Arcs) = DepInfo :-
|
|
% digraph.return_sccs_in_to_from_order puts the cliques of parents
|
|
% after the cliques of their children. This is a bottom down order.
|
|
BottomUpOrdering = digraph.return_sccs_in_to_from_order(Graph),
|
|
DepInfo = dependency_info(Graph, Arcs, BottomUpOrdering).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
dependency_info_get_graph(DepInfo) = DepInfo ^ dep_graph.
|
|
dependency_info_get_arcs(DepInfo) = DepInfo ^ dep_arcs.
|
|
dependency_info_get_bottom_up_sccs(DepInfo) = DepInfo ^ dep_bottom_up_sccs.
|
|
|
|
dependency_info_get_condensed_bottom_up_sccs(DepInfo) = CondensedOrder :-
|
|
ListOfSets = dependency_info_get_bottom_up_sccs(DepInfo),
|
|
list.map(set.to_sorted_list, ListOfSets, ListOfLists),
|
|
list.condense(ListOfLists, CondensedOrder).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
|
|
dependency_info_make_scc_map(DepInfo) = SCCMap :-
|
|
SCCs = dependency_info_get_bottom_up_sccs(DepInfo),
|
|
list.foldl(add_scc_entries_to_scc_map, SCCs, init, SCCMap).
|
|
|
|
:- pred add_scc_entries_to_scc_map(set(T)::in,
|
|
scc_map(T)::in, scc_map(T)::out) is det.
|
|
|
|
add_scc_entries_to_scc_map(SCC, !Map) :-
|
|
set.fold(add_scc_entry_to_scc_map(SCC), SCC, !Map).
|
|
|
|
:- pred add_scc_entry_to_scc_map(set(T)::in, T::in,
|
|
scc_map(T)::in, scc_map(T)::out) is det.
|
|
|
|
add_scc_entry_to_scc_map(SCC, Node, !Map) :-
|
|
map.det_insert(Node, SCC, !Map).
|
|
|
|
%-----------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------%
|