mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
compiler/add_heap_ops.m:
compiler/check_import_accessibility.m:
compiler/comp_unit_interface.m:
compiler/convert_import_use.m:
compiler/deforest.m:
compiler/dep_par_conj.m:
compiler/distance_granularity.m:
compiler/equiv_type.m:
compiler/generate_dep_d_files.m:
compiler/generate_mmakefile_fragments.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/higher_order.specialize_unify_compare.m:
compiler/jumpopt.m:
compiler/layout_out.m:
compiler/lco.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds_out_file.m:
compiler/make.build.m:
compiler/make.get_module_dep_info.m:
compiler/make.library_install.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.track_flags.m:
compiler/make_hlds_passes.m:
compiler/make_module_file_names.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_lookup_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_target_util.m:
compiler/module_cmds.m:
compiler/opt_deps_spec.m:
compiler/optimize.m:
compiler/parse_dcg_goal.m:
compiler/parse_goal.m:
compiler/parse_item.m:
compiler/parse_module.m:
compiler/parse_string_format.m:
compiler/proc_gen.m:
compiler/prop_mode_constraints.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.region_analysis.m:
compiler/rbmm.region_transformation.m:
compiler/simplify_goal_disj.m:
compiler/ssdebug.m:
compiler/stack_opt.m:
compiler/string_switch.m:
compiler/switch_gen.m:
compiler/term_constr_build.m:
compiler/trace_gen.m:
compiler/tupling.m:
compiler/untupling.m:
compiler/write_deps_file.m:
deep_profiler/autopar_calc_overlap.m:
deep_profiler/autopar_find_best_par.m:
deep_profiler/html_format.m:
deep_profiler/startup.m:
profiler/mercury_profile.m:
profiler/propagate.m:
Act on the new warnings. In a few cases, conform to the changes
resulting from acting on the warnings in other modules.
browser/Mercury.options:
compiler/Mercury.options:
library/Mercury.options:
mdbcomp/Mercury.options:
ssdb/Mercury.options:
Specify options for disabling the new warnings for modules
where we (probably) won't want them.
configure.ac:
Require the installed compiler to understand the options that
we now reference in the Mercury.options files above.
tests/debugger/tailrec1.exp:
Expect variable names for the middle versions of state vars
using the new naming scheme.
tests/invalid/Mercury.options:
Fix references to obsolete test names.
tests/warnings/Mercury.options:
Avoid a test failure with intermodule optimization.
1305 lines
53 KiB
Mathematica
1305 lines
53 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1996-2011 The University of Melbourne.
|
|
% Copyright (C) 2015-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: get_dependencies.m.
|
|
%
|
|
% This module finds out what other things the contents of a given module
|
|
% depend on. These "things" can be
|
|
%
|
|
% - other Mercury modules that this module imports or uses,
|
|
% - files containing fact tables, or
|
|
% - foreign language source or header files.
|
|
%
|
|
% XXX ITEM_LIST Most of the work done in this module is now done
|
|
% more directly and simply in grab_modules.m. When we switch over to using
|
|
% the new code in modules.m exclusively, most or even all of this module
|
|
% shouldn't be needed anymore.
|
|
%
|
|
% XXX If some parts of this module survive this transition period,
|
|
% we should either factor out (if possible) or at least document
|
|
% the commonalities between the code here and in grab_modules.m.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.get_dependencies.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_data_foreign.
|
|
:- import_module parse_tree.prog_item.
|
|
:- import_module parse_tree.prog_parse_tree.
|
|
|
|
:- import_module list.
|
|
:- import_module set.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_explicit_and_implicit_avail_needs_in_parse_tree_plain_opt(
|
|
parse_tree_plain_opt::in,
|
|
set(module_name)::out, implicit_avail_needs::out) is det.
|
|
|
|
% get_implicit_avail_needs_in_aug_compilation_unit(Globals, AugCompUnit,
|
|
% ImplicitlyUsedModules):
|
|
%
|
|
% Get the list of builtin modules (e.g. profiling_builtin.m,
|
|
% table_builtin.m etc)_ that the given items may implicitly depend on.
|
|
% and which should be automatically implicitly made available
|
|
% as if via `:- use_module'.
|
|
%
|
|
% The module builtin.m should *always* be implicitly made available
|
|
% as if via `:- import_module'.
|
|
%
|
|
:- pred get_implicit_avail_needs_in_aug_compilation_unit(globals::in,
|
|
aug_compilation_unit::in, set(module_name)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type maybe_need_tabling
|
|
---> do_not_need_tabling
|
|
; do_need_tabling.
|
|
|
|
:- type maybe_need_tabling_statistics
|
|
---> do_not_need_tabling_statistics
|
|
; do_need_tabling_statistics.
|
|
|
|
:- type maybe_need_stm
|
|
---> do_not_need_stm
|
|
; do_need_stm.
|
|
|
|
:- type maybe_need_exception
|
|
---> do_not_need_exception
|
|
; do_need_exception.
|
|
|
|
:- type maybe_need_string_format
|
|
---> do_not_need_string_format
|
|
; do_need_string_format.
|
|
|
|
:- type maybe_need_stream_format
|
|
---> do_not_need_stream_format
|
|
; do_need_stream_format.
|
|
|
|
:- type maybe_need_io
|
|
---> do_not_need_io
|
|
; do_need_io.
|
|
|
|
% A representation of which builtin modules a set of items
|
|
% implicitly needs imported or used.
|
|
%
|
|
% XXX We currently discover the need to import the modules needed
|
|
% to compile away format strings by traversing all parts of all clauses,
|
|
% and checking every predicate name and functor name to see whether
|
|
% it *could* refer to any of the predicates recognized by the
|
|
% is_builtin_format_call predicate. This is inefficient. It is also
|
|
% a bit unpredictable, since it will lead us to implicitly import
|
|
% those modules even if a call to unqualified("format") eventually
|
|
% turns out to call some other predicate of that name.
|
|
%
|
|
% We should therefore consider ALWAYS implicitly importing the predicates
|
|
% needed by format_call.m.
|
|
:- type implicit_avail_needs
|
|
---> implicit_avail_needs(
|
|
ian_tabling :: maybe_need_tabling,
|
|
ian_tabling_statistics :: maybe_need_tabling_statistics,
|
|
ian_stm :: maybe_need_stm,
|
|
ian_exception :: maybe_need_exception,
|
|
ian_string_format :: maybe_need_string_format,
|
|
ian_stream_format :: maybe_need_stream_format,
|
|
ian_io :: maybe_need_io
|
|
).
|
|
|
|
:- func init_implicit_avail_needs = implicit_avail_needs.
|
|
|
|
:- pred combine_implicit_needs(list(implicit_avail_needs)::in,
|
|
implicit_avail_needs::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_instance(item_instance_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
:- pred acc_implicit_avail_needs_in_instance_method(instance_method::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
:- pred acc_implicit_avail_needs_in_mutable(item_mutable_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
:- pred acc_implicit_avail_needs_in_clause(item_clause_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
:- pred acc_implicit_avail_needs_in_goal(goal::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
% compute_implicit_avail_needs(Globals, ImplicitAvailNeeds,
|
|
% ImplicitlyUsedModules):
|
|
%
|
|
% Given ImplicitAvailNeeds, a data structure generated by
|
|
% starting with init_implicit_avail_needs and then gathering
|
|
% implicit import needs using calls to acc_implicit_avail_needs_in_*
|
|
% return the set of modules that the items processed implicitly need used.
|
|
% The set of modules that any set of items implicitly need imported
|
|
% is *always* the singleton set containing only builtin.m.
|
|
%
|
|
:- pred compute_implicit_avail_needs(globals::in, implicit_avail_needs::in,
|
|
set(module_name)::out) is det.
|
|
|
|
% extend_import_and_or_use_map_with_implicits(Globals,
|
|
% IntImplicitAvailNeeds, ImpImplicitAvailNeeds, !ImportUseMap):
|
|
%
|
|
% Given an ImplicitAvailNeeds structure for both the interface
|
|
% and the implementation sections of a module, record the implicit
|
|
% imports and/or uses they encode to !ImportUseMap.
|
|
%
|
|
:- pred extend_import_and_or_use_map_with_implicits(globals::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::in,
|
|
import_and_or_use_map::in, import_and_or_use_map::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_fim_specs(parse_tree_module_src::in, set(fim_spec)::out) is det.
|
|
|
|
:- pred get_fact_tables(parse_tree_module_src::in, set(string)::out) is det.
|
|
|
|
:- pred get_foreign_include_file_infos(parse_tree_module_src::in,
|
|
set(foreign_include_file_info)::out) is det.
|
|
|
|
:- pred get_foreign_export_langs(parse_tree_module_src::in,
|
|
set(foreign_language)::out) is det.
|
|
|
|
:- pred get_foreign_code_langs(parse_tree_module_src::in,
|
|
set(foreign_language)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.options.
|
|
:- import_module mdbcomp.builtin_modules.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module parse_tree.item_util.
|
|
:- import_module parse_tree.maybe_error.
|
|
:- import_module parse_tree.prog_data_pragma.
|
|
:- import_module parse_tree.prog_foreign.
|
|
|
|
:- import_module bool.
|
|
:- import_module cord.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module one_or_more.
|
|
:- import_module require.
|
|
:- import_module term.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
get_explicit_and_implicit_avail_needs_in_parse_tree_plain_opt(
|
|
ParseTreePlainOpt, ExplicitModules, ImplicitAvailNeeds) :-
|
|
ParseTreePlainOpt = parse_tree_plain_opt(_ModuleName, _ModuleNameContext,
|
|
UseMap, _FIMSpecs, _TypeDefns, _ForeignEnums,
|
|
_InstDefns, _ModeDefns, _TypeClasses, _Instances,
|
|
_PredDecls, _ModeDecls, _Clauses, _ForeignProcs, _Promises,
|
|
_DeclMarkers, _ImplMarkers, _TypeSpecs,
|
|
_UnusedArgs, _TermInfos, _Term2Infos,
|
|
_Exceptions, _Trailings, _MMTablings, _Sharings, _Reuses),
|
|
map.keys_as_set(UseMap, ExplicitModules),
|
|
acc_implicit_avail_needs_in_parse_tree_plain_opt(ParseTreePlainOpt,
|
|
init_implicit_avail_needs, ImplicitAvailNeeds).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
get_implicit_avail_needs_in_aug_compilation_unit(Globals, AugCompUnit,
|
|
ImplicitlyUsedModules) :-
|
|
ImplicitAvailNeeds0 = init_implicit_avail_needs,
|
|
acc_implicit_avail_needs_in_aug_compilation_unit(AugCompUnit,
|
|
ImplicitAvailNeeds0, ImplicitAvailNeeds),
|
|
compute_implicit_avail_needs(Globals, ImplicitAvailNeeds,
|
|
ImplicitlyUsedModules).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
init_implicit_avail_needs = ImplicitAvailNeeds :-
|
|
ImplicitAvailNeeds = implicit_avail_needs(do_not_need_tabling,
|
|
do_not_need_tabling_statistics, do_not_need_stm, do_not_need_exception,
|
|
do_not_need_string_format, do_not_need_stream_format, do_not_need_io).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
combine_implicit_needs(ImplicitNeedsList, ImplicitNeeds) :-
|
|
combine_implicit_needs_acc(ImplicitNeedsList,
|
|
do_not_need_tabling, NeedTabling,
|
|
do_not_need_tabling_statistics, NeedTablingStatistics,
|
|
do_not_need_stm, NeedStm,
|
|
do_not_need_exception, NeedException,
|
|
do_not_need_string_format, NeedStringFormat,
|
|
do_not_need_stream_format, NeedStreamFormat,
|
|
do_not_need_io, NeedIO),
|
|
ImplicitNeeds = implicit_avail_needs(NeedTabling, NeedTablingStatistics,
|
|
NeedStm, NeedException, NeedStringFormat, NeedStreamFormat, NeedIO).
|
|
|
|
:- pred combine_implicit_needs_acc(list(implicit_avail_needs)::in,
|
|
maybe_need_tabling::in, maybe_need_tabling::out,
|
|
maybe_need_tabling_statistics::in, maybe_need_tabling_statistics::out,
|
|
maybe_need_stm::in, maybe_need_stm::out,
|
|
maybe_need_exception::in, maybe_need_exception::out,
|
|
maybe_need_string_format::in, maybe_need_string_format::out,
|
|
maybe_need_stream_format::in, maybe_need_stream_format::out,
|
|
maybe_need_io::in, maybe_need_io::out) is det.
|
|
|
|
combine_implicit_needs_acc([], !NeedTabling,
|
|
!NeedTablingStatistics, !NeedStm, !NeedException,
|
|
!NeedStringFormat, !NeedStreamFormat, !NeedIO).
|
|
combine_implicit_needs_acc([Head | Tail], !NeedTabling,
|
|
!NeedTablingStatistics, !NeedStm, !NeedException,
|
|
!NeedStringFormat, !NeedStreamFormat, !NeedIO) :-
|
|
Head = implicit_avail_needs(NeedTabling, NeedTablingStatistics,
|
|
NeedStm, NeedException, NeedStringFormat, NeedStreamFormat, NeedIO),
|
|
% XXX ARGPACK
|
|
% If argument packing is enabled, it *should* be possible for the compiler
|
|
% to replace this sequence of seven switches with a *single* bitwise OR
|
|
% operation. Check whether this is the case.
|
|
(
|
|
NeedTabling = do_not_need_tabling
|
|
;
|
|
NeedTabling = do_need_tabling,
|
|
!:NeedTabling = do_need_tabling
|
|
),
|
|
(
|
|
NeedTablingStatistics = do_not_need_tabling_statistics
|
|
;
|
|
NeedTablingStatistics = do_need_tabling_statistics,
|
|
!:NeedTablingStatistics = do_need_tabling_statistics
|
|
),
|
|
(
|
|
NeedStm = do_not_need_stm
|
|
;
|
|
NeedStm = do_need_stm,
|
|
!:NeedStm = do_need_stm
|
|
),
|
|
(
|
|
NeedException = do_not_need_exception
|
|
;
|
|
NeedException = do_need_exception,
|
|
!:NeedException = do_need_exception
|
|
),
|
|
(
|
|
NeedStringFormat = do_not_need_string_format
|
|
;
|
|
NeedStringFormat = do_need_string_format,
|
|
!:NeedStringFormat = do_need_string_format
|
|
),
|
|
(
|
|
NeedStreamFormat = do_not_need_stream_format
|
|
;
|
|
NeedStreamFormat = do_need_stream_format,
|
|
!:NeedStreamFormat = do_need_stream_format
|
|
),
|
|
(
|
|
NeedIO = do_not_need_io
|
|
;
|
|
NeedIO = do_need_io,
|
|
!:NeedIO = do_need_io
|
|
),
|
|
combine_implicit_needs_acc(Tail, !NeedTabling,
|
|
!NeedTablingStatistics, !NeedStm, !NeedException,
|
|
!NeedStringFormat, !NeedStreamFormat, !NeedIO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_aug_compilation_unit(
|
|
aug_compilation_unit::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_aug_compilation_unit(AugCompUnit,
|
|
!ImplicitAvailNeeds) :-
|
|
AugCompUnit = aug_compilation_unit(ParseTreeModuleSrc,
|
|
AncestorIntSpecs, DirectInt1Specs, IndirectInt2Specs,
|
|
PlainOpts, TransOpts, IntForOptSpecs, _TypeRepnSpecs,
|
|
_MaybeVersionNumbers),
|
|
acc_implicit_avail_needs_in_parse_tree_module_src(ParseTreeModuleSrc,
|
|
!ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_ancestor_int_spec,
|
|
AncestorIntSpecs, !ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_direct_int1_spec,
|
|
DirectInt1Specs, !ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_indirect_int2_spec,
|
|
IndirectInt2Specs, !ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_int_for_opt_spec,
|
|
IntForOptSpecs, !ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_parse_tree_plain_opt,
|
|
PlainOpts, !ImplicitAvailNeeds),
|
|
map.foldl_values(acc_implicit_avail_needs_in_parse_tree_trans_opt,
|
|
TransOpts, !ImplicitAvailNeeds).
|
|
% The only things we pay attention to inside _TypeRepnSpecs
|
|
% are type_repn items, which have no implicit avail needs.
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_module_src(
|
|
parse_tree_module_src::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_module_src(ParseTreeModuleSrc,
|
|
!ImplicitAvailNeeds) :-
|
|
ParseTreeModuleSrc = parse_tree_module_src(_ModuleName, _ModuleNameContext,
|
|
_InclMap, _ImportUseMap,
|
|
_IntFIMSpecMap, _ImpFIMSpecMap, _IntSelfFIMLangs, _ImpSelfFIMLangs,
|
|
|
|
TypeCtorCheckedMap, _InstCtorCheckedMap, _ModeCtorCheckedMap,
|
|
_TypeSpecs, _InstModeSpecs,
|
|
|
|
_IntTypeClasses, IntInstances, _IntPredDecls, _IntModeDecls,
|
|
_IntDeclPragmas, _IntDeclMarkers, IntPromises, _IntBadPreds,
|
|
|
|
_ImpTypeClasses, ImpInstances, _ImpPredDecls, _ImpModeDecls,
|
|
ImpClauses, _ImpForeignProcs, _ImpForeignExportEnums,
|
|
_ImpDeclPragmas, _ImpDeclMarkers, ImpImplPragmas, _ImpImplMarkers,
|
|
ImpPromises, _ImpInitialises, _ImpFinalises, ImpMutables),
|
|
|
|
type_ctor_checked_map_get_src_defns(TypeCtorCheckedMap,
|
|
_IntTypeDefns, ImpTypeDefns, _ImpForeignEnums),
|
|
% acc_implicit_avail_needs_in_type_defn can add to !ImplicitAvailNeeds
|
|
% only for solver type definitions, and solver types can be only
|
|
% *declared* in interface sections. Therefore calling that predicate
|
|
% on _IntTypeDefns would do nothing.
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
IntInstances, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_promise,
|
|
IntPromises, !ImplicitAvailNeeds),
|
|
|
|
list.foldl(acc_implicit_avail_needs_in_type_defn,
|
|
ImpTypeDefns, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
ImpInstances, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_clause,
|
|
ImpClauses, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_impl_pragma,
|
|
ImpImplPragmas, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_promise,
|
|
ImpPromises, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_mutable,
|
|
ImpMutables, !ImplicitAvailNeeds).
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_ancestor_int_spec(ancestor_int_spec::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_ancestor_int_spec(AncestorIntSpec,
|
|
!ImplicitAvailNeeds) :-
|
|
AncestorIntSpec = ancestor_int0(ParseTreeInt0, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int0(ParseTreeInt0,
|
|
!ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_direct_int1_spec(direct_int1_spec::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_direct_int1_spec(DirectInt1Spec,
|
|
!ImplicitAvailNeeds) :-
|
|
DirectInt1Spec = direct_int1(ParseTreeInt1, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int1(ParseTreeInt1,
|
|
!ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_indirect_int2_spec(indirect_int2_spec::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_indirect_int2_spec(IndirectInt2Spec,
|
|
!ImplicitAvailNeeds) :-
|
|
IndirectInt2Spec = indirect_int2(ParseTreeInt2, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int2(ParseTreeInt2,
|
|
!ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_int_for_opt_spec(int_for_opt_spec::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_int_for_opt_spec(IntForOptIntSpec,
|
|
!ImplicitAvailNeeds) :-
|
|
(
|
|
IntForOptIntSpec = for_opt_int0(ParseTreeInt0, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int0(ParseTreeInt0,
|
|
!ImplicitAvailNeeds)
|
|
;
|
|
IntForOptIntSpec = for_opt_int1(ParseTreeInt1, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int1(ParseTreeInt1,
|
|
!ImplicitAvailNeeds)
|
|
;
|
|
IntForOptIntSpec = for_opt_int2(ParseTreeInt2, _),
|
|
acc_implicit_avail_needs_in_parse_tree_int2(ParseTreeInt2,
|
|
!ImplicitAvailNeeds)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_int0(parse_tree_int0::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_int0(ParseTreeInt0,
|
|
!ImplicitAvailNeeds) :-
|
|
ParseTreeInt0 = parse_tree_int0(_ModuleName, _ModuleNameContext,
|
|
_MaybeVersionNumbers, _InclMap,
|
|
_ImportUseMap, _IntFIMSpecs, _ImpFIMSpecs,
|
|
TypeCtorCheckedMap, _InstCtorCheckedMap, _ModeCtorCheckedMap,
|
|
_IntTypeClasses, IntInstances, _IntPredDecls, _IntModeDecls,
|
|
_IntDeclPragmas, _IntDeclMarkers, IntPromises,
|
|
_ImpTypeClasses, ImpInstances, _ImpPredDecls, _ImpModeDecls,
|
|
_ImpDeclPragmas, _ImpDeclMarkers, ImpPromises),
|
|
|
|
map.foldl_values(acc_implicit_avail_needs_in_type_ctor_checked_defn,
|
|
TypeCtorCheckedMap, !ImplicitAvailNeeds),
|
|
% XXX IMPLICIT Instance items in the interface must be abstract,
|
|
% so they cannot have any implicit avail needs.
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
coerce(IntInstances), !ImplicitAvailNeeds),
|
|
% XXX IMPLICIT None of the implicit avail needs this call looks for
|
|
% has any business occurring in a promise.
|
|
list.foldl(acc_implicit_avail_needs_in_promise,
|
|
IntPromises, !ImplicitAvailNeeds),
|
|
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
coerce(ImpInstances), !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_promise,
|
|
ImpPromises, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_int1(parse_tree_int1::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_int1(ParseTreeInt1,
|
|
!ImplicitAvailNeeds) :-
|
|
ParseTreeInt1 = parse_tree_int1(_ModuleName, _ModuleNameContext,
|
|
_MaybeVersionNumbers, _InclMap,
|
|
_ImportUseMap, _IntFIMSpecs, _ImpFIMSpecs,
|
|
TypeDefnCheckedMap, _InstDefnCheckedMap, _ModeDefnCheckedMap,
|
|
_IntTypeClasses, IntInstances, _IntPredDecls, _IntModeDecls,
|
|
_IntDeclPragmas, _IntDeclMarkers, IntPromises, _IntTypeRepnMap,
|
|
_ImpTypeClasses),
|
|
|
|
map.foldl_values(acc_implicit_avail_needs_in_type_ctor_checked_defn,
|
|
TypeDefnCheckedMap, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
coerce(IntInstances), !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_promise,
|
|
IntPromises, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_int2(parse_tree_int2::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_int2(ParseTreeInt2,
|
|
!ImplicitAvailNeeds) :-
|
|
ParseTreeInt2 = parse_tree_int2(_ModuleName, _ModuleNameContext,
|
|
_MaybeVersionNumbers, _InclMap,
|
|
_ImportUseMap, _IntFIMSpecs, _ImpFIMSpecs,
|
|
TypeDefnCheckedMap, _InstDefnCheckedMap, _ModeDefnCheckedMap,
|
|
_IntTypeClasses, IntInstances, _IntTypeRepnMap),
|
|
|
|
map.foldl_values(acc_implicit_avail_needs_in_type_ctor_checked_defn,
|
|
TypeDefnCheckedMap, !ImplicitAvailNeeds),
|
|
% XXX IMPLICIT Instance items in the interface must be abstract,
|
|
% so they cannot have any implicit avail needs.
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
coerce(IntInstances), !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_plain_opt(
|
|
parse_tree_plain_opt::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_plain_opt(ParseTreePlainOpt,
|
|
!ImplicitAvailNeeds) :-
|
|
ParseTreePlainOpt = parse_tree_plain_opt(_ModuleName, _ModuleNameContext,
|
|
_UsedModuleNames, _FIMSpecs, TypeDefns, _ForeignEnums,
|
|
_InstDefns, _ModeDefns, _TypeClasses, Instances,
|
|
_PredDecls, _ModeDecls, Clauses, _ForeignProcs, _Promises,
|
|
_DeclMarkers, _ImplMarkers, _TypeSpecs,
|
|
_UnusedArgs, _TermInfos, _Term2Infos,
|
|
_Exceptions, _Trailings, _MMTablings, _Sharings, _Reuses),
|
|
list.foldl(acc_implicit_avail_needs_in_type_defn,
|
|
TypeDefns, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_instance,
|
|
Instances, !ImplicitAvailNeeds),
|
|
list.foldl(acc_implicit_avail_needs_in_clause,
|
|
Clauses, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_parse_tree_trans_opt(
|
|
parse_tree_trans_opt::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_parse_tree_trans_opt(ParseTreeTransOpt,
|
|
ImplicitAvailNeeds, ImplicitAvailNeeds) :-
|
|
ParseTreeTransOpt = parse_tree_trans_opt(_ModuleName, _ModuleNameContext,
|
|
_TermInfos, _Term2Infos, _Exceptions, _Trailings, _MMTablings,
|
|
_Sharings, _Reuses).
|
|
% None of the item kinds in parse_tree_trans_opts can have any
|
|
% implicit avail needs.
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_implicit_avail_needs_in_type_ctor_checked_defn(
|
|
type_ctor_checked_defn::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_type_ctor_checked_defn(CheckedDefn,
|
|
!ImplicitAvailNeeds) :-
|
|
(
|
|
CheckedDefn = checked_defn_solver(SolverDefn, _SrcDefns),
|
|
(
|
|
SolverDefn = solver_type_abstract(_, _)
|
|
;
|
|
SolverDefn = solver_type_full(_MaybeAbsDefn, ItemTypeDefnSolver),
|
|
% XXX IMPLICIT None of the implicit avail needs this call looks for
|
|
% has any business occurring in a solver type.
|
|
acc_implicit_avail_needs_in_type_defn_solver(ItemTypeDefnSolver,
|
|
!ImplicitAvailNeeds)
|
|
)
|
|
;
|
|
CheckedDefn = checked_defn_std(_, _)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_type_defn(item_type_defn_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_type_defn(ItemTypeDefn, !ImplicitAvailNeeds) :-
|
|
ItemTypeDefn = item_type_defn_info(_TypeCtorName, _TypeParams,
|
|
TypeDefn, _TVarSet, _Context, _SeqNum),
|
|
(
|
|
( TypeDefn = parse_tree_du_type(_)
|
|
; TypeDefn = parse_tree_sub_type(_)
|
|
; TypeDefn = parse_tree_eqv_type(_)
|
|
; TypeDefn = parse_tree_abstract_type(_)
|
|
; TypeDefn = parse_tree_foreign_type(_)
|
|
)
|
|
;
|
|
TypeDefn = parse_tree_solver_type(DetailsSolver),
|
|
% XXX IMPLICIT None of the implicit avail needs this call looks for
|
|
% has any business occurring in a solver type.
|
|
acc_implicit_avail_needs_in_solver_details(DetailsSolver,
|
|
!ImplicitAvailNeeds)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_type_defn_solver(
|
|
item_type_defn_info_solver::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_type_defn_solver(ItemTypeDefn,
|
|
!ImplicitAvailNeeds) :-
|
|
ItemTypeDefn = item_type_defn_info(_TypeCtorName, _TypeParams,
|
|
DetailsSolver, _TVarSet, _Context, _SeqNum),
|
|
acc_implicit_avail_needs_in_solver_details(DetailsSolver,
|
|
!ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_solver_details(type_details_solver::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_solver_details(DetailsSolver,
|
|
!ImplicitAvailNeeds) :-
|
|
DetailsSolver = type_details_solver(SolverTypeDetails,
|
|
_MaybeUnifyComparePredNames),
|
|
SolverTypeDetails = solver_type_details(_RepresentationType,
|
|
_GroundInst, _AnyInst, MutableItems),
|
|
list.foldl(acc_implicit_avail_needs_in_mutable, MutableItems,
|
|
!ImplicitAvailNeeds).
|
|
|
|
acc_implicit_avail_needs_in_instance(ItemInstance, !ImplicitAvailNeeds) :-
|
|
ItemInstance = item_instance_info(_DerivingClass, _ClassName,
|
|
_Types, _OriginalTypes, InstanceBody, _VarSet,
|
|
_ModuleContainingInstance, _Context, _SeqNum),
|
|
(
|
|
InstanceBody = instance_body_abstract
|
|
;
|
|
InstanceBody = instance_body_concrete(InstanceMethods),
|
|
list.foldl(acc_implicit_avail_needs_in_instance_method,
|
|
InstanceMethods, !ImplicitAvailNeeds)
|
|
).
|
|
|
|
acc_implicit_avail_needs_in_instance_method(InstanceMethod,
|
|
!ImplicitAvailNeeds) :-
|
|
InstanceMethod = instance_method(_MethodName, ProcDef, _Context),
|
|
(
|
|
ProcDef = instance_proc_def_name(_Name)
|
|
;
|
|
ProcDef = instance_proc_def_clauses(ItemClausesCord),
|
|
cord.foldl_pred(acc_implicit_avail_needs_in_clause, ItemClausesCord,
|
|
!ImplicitAvailNeeds)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_impl_pragma(item_impl_pragma_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_impl_pragma(ImplPragma,
|
|
!ImplicitAvailNeeds) :-
|
|
(
|
|
ImplPragma = impl_pragma_tabled(TableInfo),
|
|
TableInfo = impl_pragma_tabled_info(_, _, MaybeAttributes, _, _),
|
|
!ImplicitAvailNeeds ^ ian_tabling := do_need_tabling,
|
|
(
|
|
MaybeAttributes = no
|
|
;
|
|
MaybeAttributes = yes(Attributes),
|
|
StatsAttr = Attributes ^ table_attr_statistics,
|
|
(
|
|
StatsAttr = table_gather_statistics,
|
|
!ImplicitAvailNeeds ^ ian_tabling_statistics
|
|
:= do_need_tabling_statistics
|
|
;
|
|
StatsAttr = table_do_not_gather_statistics
|
|
)
|
|
)
|
|
;
|
|
( ImplPragma = impl_pragma_foreign_decl(_)
|
|
; ImplPragma = impl_pragma_foreign_code(_)
|
|
; ImplPragma = impl_pragma_fproc_export(_)
|
|
; ImplPragma = impl_pragma_external_proc(_)
|
|
; ImplPragma = impl_pragma_fact_table(_)
|
|
; ImplPragma = impl_pragma_req_feature_set(_)
|
|
; ImplPragma = impl_pragma_req_tail_rec(_)
|
|
)
|
|
).
|
|
|
|
acc_implicit_avail_needs_in_mutable(ItemMutableInfo,
|
|
!ImplicitAvailNeeds) :-
|
|
ItemMutableInfo = item_mutable_info(_Name,
|
|
_OrigType, _Type, _OrigInst, _Inst, InitValue,
|
|
_Attrs, _VarSet, _Context, _SeqNum),
|
|
% XXX IMPLICIT None of the implicit avail needs this call looks for
|
|
% has any business occurring in a mutable.
|
|
acc_implicit_avail_needs_in_term(InitValue, !ImplicitAvailNeeds).
|
|
|
|
acc_implicit_avail_needs_in_clause(ItemClause, !ImplicitAvailNeeds) :-
|
|
ItemClause = item_clause_info(_PredOrFunc, _PredSymName, HeadTerms,
|
|
_VarSet, MaybeGoal, _Context, _SeqNum),
|
|
acc_implicit_avail_needs_in_terms(HeadTerms, !ImplicitAvailNeeds),
|
|
(
|
|
MaybeGoal = ok2(Goal, _),
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds)
|
|
;
|
|
MaybeGoal = error2(_)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_promise(item_promise_info::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_promise(ItemPromise, !ImplicitAvailNeeds) :-
|
|
ItemPromise = item_promise_info(_PromiseType, Goal, _VarSet,
|
|
_UnivQuantVars, _Context, _SeqNum),
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds).
|
|
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds) :-
|
|
(
|
|
( Goal = true_expr(_)
|
|
; Goal = fail_expr(_)
|
|
)
|
|
% Cannot contain anything that requires implicit imports.
|
|
;
|
|
( Goal = conj_expr(_, SubGoalA, SubGoalsB)
|
|
; Goal = par_conj_expr(_, SubGoalA, SubGoalsB)
|
|
),
|
|
acc_implicit_avail_needs_in_goal(SubGoalA, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goals(SubGoalsB, !ImplicitAvailNeeds)
|
|
;
|
|
( Goal = implies_expr(_, SubGoalA, SubGoalB)
|
|
; Goal = equivalent_expr(_, SubGoalA, SubGoalB)
|
|
),
|
|
acc_implicit_avail_needs_in_goal(SubGoalA, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goal(SubGoalB, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = disj_expr(_, SubGoal1, SubGoal2, SubGoals),
|
|
acc_implicit_avail_needs_in_goal(SubGoal1, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goal(SubGoal2, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goals(SubGoals, !ImplicitAvailNeeds)
|
|
;
|
|
( Goal = not_expr(_, SubGoal)
|
|
; Goal = quant_expr(_, _, _, _Vars, SubGoal)
|
|
; Goal = promise_purity_expr(_, _Purity, SubGoal)
|
|
; Goal = promise_equivalent_solutions_expr(_, _OrdVars,
|
|
_StateVars, _DotVars, _ColonVars, SubGoal)
|
|
; Goal = promise_equivalent_solution_sets_expr(_, _OrdVars,
|
|
_StateVars, _DotVars, _ColonVars, SubGoal)
|
|
; Goal = promise_equivalent_solution_arbitrary_expr(_, _OrdVars,
|
|
_StateVars, _DotVars, _ColonVars, SubGoal)
|
|
; Goal = require_detism_expr(_, _Detism, SubGoal)
|
|
; Goal = require_complete_switch_expr(_, _SwitchVar, SubGoal)
|
|
; Goal = require_switch_arms_detism_expr(_, _SwitchVar, _Detism,
|
|
SubGoal)
|
|
; Goal = disable_warnings_expr(_, _HeadWarning, _TailWarnings, SubGoal)
|
|
),
|
|
acc_implicit_avail_needs_in_goal(SubGoal, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = trace_expr(_, _CompCond, _RunCond, MaybeIO, _Mutables,
|
|
SubGoal),
|
|
(
|
|
MaybeIO = yes(_),
|
|
!ImplicitAvailNeeds ^ ian_io := do_need_io
|
|
;
|
|
MaybeIO = no
|
|
),
|
|
acc_implicit_avail_needs_in_goal(SubGoal, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = try_expr(_, _MaybeIO, SubGoal, Then, MaybeElse,
|
|
Catches, MaybeCatchAny),
|
|
!ImplicitAvailNeeds ^ ian_exception := do_need_exception,
|
|
acc_implicit_avail_needs_in_goal(SubGoal, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goal(Then, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_maybe_goal(MaybeElse,
|
|
!ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_catch_exprs(Catches,
|
|
!ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_maybe_catch_any_expr(MaybeCatchAny,
|
|
!ImplicitAvailNeeds)
|
|
;
|
|
Goal = if_then_else_expr(_, _Vars, _StateVars, Cond, Then, Else),
|
|
acc_implicit_avail_needs_in_goal(Cond, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goal(Then, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goal(Else, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = atomic_expr(_, _Outer, _Inner, _OutputVars,
|
|
MainGoal, OrElseGoals),
|
|
!ImplicitAvailNeeds ^ ian_stm := do_need_stm,
|
|
!ImplicitAvailNeeds ^ ian_exception := do_need_exception,
|
|
acc_implicit_avail_needs_in_goal(MainGoal, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goals(OrElseGoals, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = call_expr(_, CalleeSymName, Args, _Purity),
|
|
( if is_possible_format_call(CalleeSymName, FormatCallVersion) then
|
|
!ImplicitAvailNeeds ^ ian_string_format
|
|
:= do_need_string_format,
|
|
(
|
|
FormatCallVersion = format_call_non_stream
|
|
% CalleeSymName will definitely not resolve to
|
|
% stream.string_writer.format.
|
|
;
|
|
FormatCallVersion = format_call_maybe_stream,
|
|
% We don't know whether CalleeSymName will resolve to
|
|
% stream.string_writer.format, or to one of the other format
|
|
% predicates. In the presence of this uncertainty, implicitly
|
|
% importing stream.string_writer.m is the conservative course
|
|
% of action.
|
|
!ImplicitAvailNeeds ^ ian_stream_format
|
|
:= do_need_stream_format
|
|
)
|
|
else
|
|
true
|
|
),
|
|
acc_implicit_avail_needs_in_terms(Args, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = event_expr(_, _EventName, EventArgs),
|
|
acc_implicit_avail_needs_in_terms(EventArgs, !ImplicitAvailNeeds)
|
|
;
|
|
Goal = unify_expr(_, TermA, TermB, _Purity),
|
|
acc_implicit_avail_needs_in_term(TermA, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_term(TermB, !ImplicitAvailNeeds)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_goals(list(goal)::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_goals([], !ImplicitAvailNeeds).
|
|
acc_implicit_avail_needs_in_goals([Goal | Goals], !ImplicitAvailNeeds) :-
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_goals(Goals, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_maybe_goal(maybe(goal)::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_maybe_goal(no, !ImplicitAvailNeeds).
|
|
acc_implicit_avail_needs_in_maybe_goal(yes(Goal), !ImplicitAvailNeeds) :-
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_catch_exprs(list(catch_expr)::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_catch_exprs([], !ImplicitAvailNeeds).
|
|
acc_implicit_avail_needs_in_catch_exprs([CatchExpr | CatchExprs],
|
|
!ImplicitAvailNeeds) :-
|
|
CatchExpr = catch_expr(_Pattern, Goal),
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_catch_exprs(CatchExprs, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_maybe_catch_any_expr(
|
|
maybe(catch_any_expr)::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_maybe_catch_any_expr(no, !ImplicitAvailNeeds).
|
|
acc_implicit_avail_needs_in_maybe_catch_any_expr(yes(CatchAnyExpr),
|
|
!ImplicitAvailNeeds) :-
|
|
CatchAnyExpr = catch_any_expr(_Var, Goal),
|
|
acc_implicit_avail_needs_in_goal(Goal, !ImplicitAvailNeeds).
|
|
|
|
:- pred acc_implicit_avail_needs_in_term(prog_term::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_term(Term, !ImplicitAvailNeeds) :-
|
|
(
|
|
Term = variable(_Var, _Context)
|
|
;
|
|
Term = functor(Const, ArgTerms, _Context),
|
|
(
|
|
Const = atom(Atom),
|
|
( if
|
|
(
|
|
( Atom = "string.format"
|
|
; Atom = "string__format"
|
|
; Atom = "io.format"
|
|
; Atom = "io__format"
|
|
),
|
|
!ImplicitAvailNeeds ^ ian_string_format
|
|
:= do_need_string_format
|
|
;
|
|
( Atom = "format"
|
|
; Atom = "stream.format"
|
|
; Atom = "stream__format"
|
|
; Atom = "string_writer.format"
|
|
; Atom = "string_writer__format"
|
|
; Atom = "stream.string_writer.format"
|
|
; Atom = "stream.string_writer__format"
|
|
; Atom = "stream__string_writer.format"
|
|
; Atom = "stream__string_writer__format"
|
|
),
|
|
% The replacement of calls to stream.string_writer.format
|
|
% needs everything that the replacement of calls to
|
|
% string.format or io.format needs.
|
|
!ImplicitAvailNeeds ^ ian_string_format
|
|
:= do_need_string_format,
|
|
!ImplicitAvailNeeds ^ ian_stream_format
|
|
:= do_need_stream_format
|
|
)
|
|
then
|
|
% This "true" effectuates all the updates done to
|
|
% !ImplicitAvailNeeds in the condition, while ...
|
|
true
|
|
else
|
|
% ... this "true" does not.
|
|
true
|
|
)
|
|
;
|
|
( Const = integer(_, _, _, _)
|
|
; Const = string(_)
|
|
; Const = float(_)
|
|
; Const = implementation_defined(_)
|
|
)
|
|
),
|
|
acc_implicit_avail_needs_in_terms(ArgTerms, !ImplicitAvailNeeds)
|
|
).
|
|
|
|
:- pred acc_implicit_avail_needs_in_terms(list(prog_term)::in,
|
|
implicit_avail_needs::in, implicit_avail_needs::out) is det.
|
|
|
|
acc_implicit_avail_needs_in_terms([], !ImplicitAvailNeeds).
|
|
acc_implicit_avail_needs_in_terms([Term | Terms], !ImplicitAvailNeeds) :-
|
|
acc_implicit_avail_needs_in_term(Term, !ImplicitAvailNeeds),
|
|
acc_implicit_avail_needs_in_terms(Terms, !ImplicitAvailNeeds).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
compute_implicit_avail_needs(Globals, ImplicitAvailNeeds,
|
|
!:ImplicitlyUsedModules) :-
|
|
!:ImplicitlyUsedModules =
|
|
set.make_singleton_set(mercury_private_builtin_module),
|
|
ImplicitAvailNeeds = implicit_avail_needs(
|
|
ItemsNeedTabling, ItemsNeedTablingStatistics,
|
|
ItemsNeedSTM, ItemsNeedException,
|
|
ItemsNeedStringFormat, ItemsNeedStreamFormat, ItemsNeedIO),
|
|
% We should include mercury_table_builtin_module if the Items contain
|
|
% a tabling pragma, or if one of --use-minimal-model (either kind) and
|
|
% --trace-table-io is specified. In the former case, we may also need
|
|
% to import mercury_table_statistics_module.
|
|
(
|
|
ItemsNeedTabling = do_need_tabling,
|
|
set.insert(mercury_table_builtin_module, !ImplicitlyUsedModules),
|
|
(
|
|
ItemsNeedTablingStatistics = do_need_tabling_statistics,
|
|
set.insert(mercury_table_statistics_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedTablingStatistics = do_not_need_tabling_statistics
|
|
)
|
|
;
|
|
ItemsNeedTabling = do_not_need_tabling,
|
|
expect(
|
|
unify(ItemsNeedTablingStatistics, do_not_need_tabling_statistics),
|
|
$pred, "tabling statistics without tabling"),
|
|
( if
|
|
% These forms of tabling cannot ask for statistics.
|
|
(
|
|
globals.lookup_bool_option(Globals,
|
|
use_minimal_model_stack_copy, yes)
|
|
;
|
|
globals.lookup_bool_option(Globals,
|
|
use_minimal_model_own_stacks, yes)
|
|
;
|
|
globals.lookup_bool_option(Globals, trace_table_io, yes)
|
|
)
|
|
then
|
|
set.insert(mercury_table_builtin_module, !ImplicitlyUsedModules)
|
|
else
|
|
true
|
|
)
|
|
),
|
|
(
|
|
ItemsNeedSTM = do_need_stm,
|
|
set.insert(mercury_stm_builtin_module, !ImplicitlyUsedModules),
|
|
set.insert(mercury_exception_module, !ImplicitlyUsedModules),
|
|
set.insert(mercury_univ_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedSTM = do_not_need_stm
|
|
),
|
|
(
|
|
ItemsNeedException = do_need_exception,
|
|
set.insert(mercury_exception_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedException = do_not_need_exception
|
|
),
|
|
(
|
|
ItemsNeedStringFormat = do_need_string_format,
|
|
set.insert(mercury_string_format_module, !ImplicitlyUsedModules),
|
|
set.insert(mercury_string_parse_util_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedStringFormat = do_not_need_string_format
|
|
),
|
|
(
|
|
ItemsNeedStreamFormat = do_need_stream_format,
|
|
set.insert(mercury_stream_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedStreamFormat = do_not_need_stream_format
|
|
),
|
|
(
|
|
ItemsNeedIO = do_need_io,
|
|
set.insert(mercury_io_module, !ImplicitlyUsedModules)
|
|
;
|
|
ItemsNeedIO = do_not_need_io
|
|
),
|
|
globals.lookup_bool_option(Globals, profile_deep, Deep),
|
|
(
|
|
Deep = yes,
|
|
set.insert(mercury_profiling_builtin_module, !ImplicitlyUsedModules)
|
|
;
|
|
Deep = no
|
|
),
|
|
( if
|
|
(
|
|
globals.lookup_bool_option(Globals,
|
|
record_term_sizes_as_words, yes)
|
|
;
|
|
globals.lookup_bool_option(Globals,
|
|
record_term_sizes_as_cells, yes)
|
|
)
|
|
then
|
|
set.insert(mercury_term_size_prof_builtin_module,
|
|
!ImplicitlyUsedModules)
|
|
else
|
|
true
|
|
),
|
|
globals.get_target(Globals, Target),
|
|
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
|
|
globals.lookup_bool_option(Globals, parallel, Parallel),
|
|
( if
|
|
Target = target_c,
|
|
HighLevelCode = no,
|
|
Parallel = yes
|
|
then
|
|
set.insert(mercury_par_builtin_module, !ImplicitlyUsedModules)
|
|
else
|
|
true
|
|
),
|
|
globals.lookup_bool_option(Globals, use_regions, UseRegions),
|
|
(
|
|
UseRegions = yes,
|
|
set.insert(mercury_region_builtin_module, !ImplicitlyUsedModules)
|
|
;
|
|
UseRegions = no
|
|
),
|
|
globals.get_ssdb_trace_level(Globals, SSDBTraceLevel),
|
|
(
|
|
SSDBTraceLevel = ssdb_none
|
|
;
|
|
( SSDBTraceLevel = ssdb_shallow
|
|
; SSDBTraceLevel = ssdb_deep
|
|
),
|
|
globals.lookup_bool_option(Globals, force_disable_ssdebug,
|
|
DisableSSDB),
|
|
(
|
|
DisableSSDB = yes
|
|
;
|
|
DisableSSDB = no,
|
|
set.insert(mercury_ssdb_builtin_module, !ImplicitlyUsedModules)
|
|
)
|
|
).
|
|
|
|
extend_import_and_or_use_map_with_implicits(Globals,
|
|
IntImplicitAvailNeeds, ImpImplicitAvailNeeds, !ImportUseMap) :-
|
|
compute_implicit_avail_needs(Globals, IntImplicitAvailNeeds,
|
|
IntImplicitUses),
|
|
compute_implicit_avail_needs(Globals, ImpImplicitAvailNeeds,
|
|
ImpImplicitUses),
|
|
PublicBuiltin = mercury_public_builtin_module,
|
|
add_implicit_avail(implicit_int_import, PublicBuiltin, !ImportUseMap),
|
|
set.foldl(add_implicit_avail(implicit_int_use), IntImplicitUses,
|
|
!ImportUseMap),
|
|
set.foldl(add_implicit_avail(implicit_imp_use), ImpImplicitUses,
|
|
!ImportUseMap).
|
|
|
|
:- pred add_implicit_avail(implicit_import_or_use::in, module_name::in,
|
|
import_and_or_use_map::in, import_and_or_use_map::out) is det.
|
|
|
|
add_implicit_avail(Implicit, ModuleName, !ImportUseMap) :-
|
|
( if map.search(!.ImportUseMap, ModuleName, OldEntry) then
|
|
(
|
|
OldEntry = explicit_avail(Explicit),
|
|
NewEntry = implicit_avail(Implicit, yes(Explicit)),
|
|
map.det_update(ModuleName, NewEntry, !ImportUseMap)
|
|
;
|
|
OldEntry = implicit_avail(_, _)
|
|
% Since we insert implicit avails into !ImportUseMap in order
|
|
% from most general (int_import) to least general (imp_use),
|
|
% if we find any existing implicit avail for this module,
|
|
% keep it.
|
|
)
|
|
else
|
|
NewEntry = implicit_avail(Implicit, no),
|
|
map.det_insert(ModuleName, NewEntry, !ImportUseMap)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
get_fim_specs(ParseTreeModuleSrc, FIMSpecs) :-
|
|
map.keys_as_set(ParseTreeModuleSrc ^ ptms_int_fims, IntFIMSpecs),
|
|
map.keys_as_set(ParseTreeModuleSrc ^ ptms_imp_fims, ImpFIMSpecs),
|
|
some [!SelfImportLangs] (
|
|
Mutables = ParseTreeModuleSrc ^ ptms_imp_mutables,
|
|
(
|
|
Mutables = [_ | _],
|
|
!:SelfImportLangs = set.list_to_set(all_foreign_languages)
|
|
;
|
|
Mutables = [],
|
|
TypeCtorCheckedMap = ParseTreeModuleSrc ^ ptms_type_defns,
|
|
type_ctor_checked_map_get_src_defns(TypeCtorCheckedMap,
|
|
IntTypeDefns, _ImpTypeDefns, ImpForeignEnums),
|
|
% XXX If we collect FIMSpecs in foreign type definitions
|
|
% in the interface section, and foreign procs/enums in the
|
|
% implementation section, why do we not collect them
|
|
% in foreign type definitions in the implementation section?
|
|
ImpForeignProcs = ParseTreeModuleSrc ^ ptms_imp_foreign_procs,
|
|
ImpImplPragmas = ParseTreeModuleSrc ^ ptms_imp_impl_pragmas,
|
|
set.init(!:SelfImportLangs),
|
|
list.foldl(acc_needed_self_fim_langs_for_type_defn,
|
|
IntTypeDefns, !SelfImportLangs),
|
|
list.foldl(acc_needed_self_fim_langs_for_foreign_proc,
|
|
ImpForeignProcs, !SelfImportLangs),
|
|
list.foldl(acc_needed_self_fim_langs_for_foreign_enum,
|
|
ImpForeignEnums, !SelfImportLangs),
|
|
list.foldl(acc_needed_self_fim_langs_for_impl_pragma,
|
|
ImpImplPragmas, !SelfImportLangs)
|
|
),
|
|
ModuleName = ParseTreeModuleSrc ^ ptms_module_name,
|
|
MakeSelfFIM = (func(L) = fim_spec(L, ModuleName)),
|
|
SelfFIMSpecs = set.map(MakeSelfFIM, !.SelfImportLangs),
|
|
FIMSpecs = set.union_list([IntFIMSpecs, ImpFIMSpecs, SelfFIMSpecs])
|
|
).
|
|
|
|
get_fact_tables(ParseTreeModuleSrc, FactTables) :-
|
|
list.foldl(acc_fact_tables_from_impl_pragma,
|
|
ParseTreeModuleSrc ^ ptms_imp_impl_pragmas, set.init, FactTables).
|
|
|
|
get_foreign_include_file_infos(ParseTreeModuleSrc, FIFOs) :-
|
|
list.foldl(acc_foreign_include_file_info_from_impl_pragma,
|
|
ParseTreeModuleSrc ^ ptms_imp_impl_pragmas, set.init, FIFOs).
|
|
|
|
get_foreign_export_langs(ParseTreeModuleSrc, Langs) :-
|
|
( if
|
|
( ParseTreeModuleSrc ^ ptms_imp_initialises = [_ | _]
|
|
; ParseTreeModuleSrc ^ ptms_imp_finalises = [_ | _]
|
|
)
|
|
then
|
|
Langs = set.list_to_set(all_foreign_languages)
|
|
else
|
|
list.foldl(acc_foreign_export_langs_from_impl_pragma,
|
|
ParseTreeModuleSrc ^ ptms_imp_impl_pragmas, set.init, Langs)
|
|
).
|
|
|
|
get_foreign_code_langs(ParseTreeModuleSrc, Langs) :-
|
|
( if
|
|
( ParseTreeModuleSrc ^ ptms_imp_mutables = [_ | _]
|
|
; ParseTreeModuleSrc ^ ptms_imp_initialises = [_ | _]
|
|
; ParseTreeModuleSrc ^ ptms_imp_finalises = [_ | _]
|
|
)
|
|
then
|
|
Langs = set.list_to_set(all_foreign_languages)
|
|
else
|
|
list.foldl(acc_foreign_code_langs_from_foreign_proc,
|
|
ParseTreeModuleSrc ^ ptms_imp_foreign_procs, set.init, Langs1),
|
|
list.foldl(acc_foreign_code_langs_from_impl_pragma,
|
|
ParseTreeModuleSrc ^ ptms_imp_impl_pragmas, Langs1, Langs)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred acc_foreign_include_file_info_from_impl_pragma(
|
|
item_impl_pragma_info::in,
|
|
set(foreign_include_file_info)::in, set(foreign_include_file_info)::out)
|
|
is det.
|
|
|
|
acc_foreign_include_file_info_from_impl_pragma(ImplPragma, !FIFOs) :-
|
|
(
|
|
(
|
|
ImplPragma = impl_pragma_foreign_decl(FDInfo),
|
|
FDInfo = impl_pragma_foreign_decl_info(Lang, _, LiteralOrInclude,
|
|
_, _)
|
|
;
|
|
ImplPragma = impl_pragma_foreign_code(FCInfo),
|
|
FCInfo = impl_pragma_foreign_code_info(Lang, LiteralOrInclude,
|
|
_, _)
|
|
),
|
|
(
|
|
LiteralOrInclude = floi_literal(_)
|
|
;
|
|
LiteralOrInclude = floi_include_file(FileName),
|
|
FIFO = foreign_include_file_info(Lang, FileName),
|
|
set.insert(FIFO, !FIFOs)
|
|
)
|
|
;
|
|
( ImplPragma = impl_pragma_fproc_export(_)
|
|
; ImplPragma = impl_pragma_fact_table(_)
|
|
; ImplPragma = impl_pragma_tabled(_)
|
|
; ImplPragma = impl_pragma_external_proc(_)
|
|
; ImplPragma = impl_pragma_req_tail_rec(_)
|
|
; ImplPragma = impl_pragma_req_feature_set(_)
|
|
)
|
|
).
|
|
|
|
:- pred acc_fact_tables_from_impl_pragma(item_impl_pragma_info::in,
|
|
set(string)::in, set(string)::out) is det.
|
|
|
|
acc_fact_tables_from_impl_pragma(ImplPragma, !FactTables) :-
|
|
(
|
|
ImplPragma = impl_pragma_fact_table(FactTableInfo),
|
|
FactTableInfo =
|
|
impl_pragma_fact_table_info(_PredNameArity, FileName, _, _),
|
|
set.insert(FileName, !FactTables)
|
|
;
|
|
( ImplPragma = impl_pragma_foreign_decl(_)
|
|
; ImplPragma = impl_pragma_foreign_code(_)
|
|
; ImplPragma = impl_pragma_fproc_export(_)
|
|
; ImplPragma = impl_pragma_tabled(_)
|
|
; ImplPragma = impl_pragma_external_proc(_)
|
|
; ImplPragma = impl_pragma_req_tail_rec(_)
|
|
; ImplPragma = impl_pragma_req_feature_set(_)
|
|
)
|
|
).
|
|
|
|
:- pred acc_foreign_export_langs_from_impl_pragma(item_impl_pragma_info::in,
|
|
set(foreign_language)::in, set(foreign_language)::out) is det.
|
|
|
|
acc_foreign_export_langs_from_impl_pragma(ImplPragma, !Langs) :-
|
|
(
|
|
ImplPragma = impl_pragma_fproc_export(FPEInfo),
|
|
FPEInfo = impl_pragma_fproc_export_info(_, Lang, _, _, _, _, _),
|
|
set.insert(Lang, !Langs)
|
|
;
|
|
( ImplPragma = impl_pragma_foreign_decl(_)
|
|
; ImplPragma = impl_pragma_foreign_code(_)
|
|
; ImplPragma = impl_pragma_fact_table(_)
|
|
; ImplPragma = impl_pragma_tabled(_)
|
|
; ImplPragma = impl_pragma_external_proc(_)
|
|
; ImplPragma = impl_pragma_req_tail_rec(_)
|
|
; ImplPragma = impl_pragma_req_feature_set(_)
|
|
)
|
|
).
|
|
|
|
:- pred acc_foreign_code_langs_from_foreign_proc(item_foreign_proc_info::in,
|
|
set(foreign_language)::in, set(foreign_language)::out) is det.
|
|
|
|
acc_foreign_code_langs_from_foreign_proc(FPInfo, !Langs) :-
|
|
FPInfo = item_foreign_proc_info(Attrs, _Name, _, _, _, _, _, _, _),
|
|
Lang = get_foreign_language(Attrs),
|
|
% NOTE We used to keep a record of the set of foreign languages
|
|
% in which there was a foreign_proc for a given procedure,
|
|
% and then chose the one in the *preferred* foreign language.
|
|
% This made sense when we had the IL backend, which could handle
|
|
% foreign procs in both IL and C#, but as of Aug 2021, when
|
|
% we target a foreign language, we accept for it only the
|
|
% foreign procs in that language, so this mechanism is unnecessary.
|
|
set.insert(Lang, !Langs).
|
|
|
|
:- pred acc_foreign_code_langs_from_impl_pragma(item_impl_pragma_info::in,
|
|
set(foreign_language)::in, set(foreign_language)::out) is det.
|
|
|
|
acc_foreign_code_langs_from_impl_pragma(ImplPragma, !Langs) :-
|
|
(
|
|
(
|
|
ImplPragma = impl_pragma_foreign_code(FCInfo),
|
|
FCInfo = impl_pragma_foreign_code_info(Lang, _LiteralOrInclude,
|
|
_, _)
|
|
;
|
|
ImplPragma = impl_pragma_fproc_export(FPEInfo),
|
|
FPEInfo = impl_pragma_fproc_export_info(_, Lang, _, _, _, _, _)
|
|
;
|
|
ImplPragma = impl_pragma_fact_table(_),
|
|
Lang = lang_c
|
|
),
|
|
set.insert(Lang, !Langs)
|
|
;
|
|
% We do NOT count foreign_decls here. We only link in a foreign object
|
|
% file if mlds_to_gcc called mlds_to_c.m to generate it, which it
|
|
% will only do if there is some foreign_code, not just foreign_decls.
|
|
% Counting foreign_decls here causes problems with intermodule
|
|
% optimization.
|
|
% XXX mlds_to_gcc.m was deleted with the rest of the gcc backend
|
|
% years ago.
|
|
( ImplPragma = impl_pragma_foreign_decl(_)
|
|
; ImplPragma = impl_pragma_tabled(_)
|
|
; ImplPragma = impl_pragma_external_proc(_)
|
|
; ImplPragma = impl_pragma_req_tail_rec(_)
|
|
; ImplPragma = impl_pragma_req_feature_set(_)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% This predicate should be kept in sync with both is_format_call and
|
|
% is_builtin_format_call_kind_and_vars in format_call.m. See the comment
|
|
% before those predicates in that module for the reason.
|
|
%
|
|
%
|
|
%
|
|
|
|
:- type format_call_version
|
|
---> format_call_non_stream
|
|
; format_call_maybe_stream.
|
|
|
|
% Can the predicate called by the given sym_name resolve to a predicate
|
|
% that this module concerns itself with? If yes, then succeed, and
|
|
% return an indication of whether this predicate *may* be one that
|
|
% requires access to stream.string_writer.m.
|
|
%
|
|
:- pred is_possible_format_call(sym_name::in, format_call_version::out)
|
|
is semidet.
|
|
|
|
is_possible_format_call(SymName, Version) :-
|
|
(
|
|
SymName = qualified(WrappedModuleName, "format"),
|
|
maybe_remove_stdlib_wrapper(WrappedModuleName, ModuleName),
|
|
(
|
|
( ModuleName = unqualified("string")
|
|
; ModuleName = unqualified("io")
|
|
; ModuleName = unqualified("builder")
|
|
; ModuleName = qualified(unqualified("string"), "builder")
|
|
),
|
|
Version = format_call_non_stream
|
|
;
|
|
( ModuleName = unqualified("stream")
|
|
; ModuleName = unqualified("string_writer")
|
|
; ModuleName = qualified(unqualified("stream"), "string_writer")
|
|
),
|
|
Version = format_call_maybe_stream
|
|
)
|
|
;
|
|
SymName = unqualified("format"),
|
|
Version = format_call_maybe_stream
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.get_dependencies.
|
|
%---------------------------------------------------------------------------%
|