Files
mercury/compiler/get_dependencies.m
Zoltan Somogyi 3dd0f2e03b Act on all remaining warnings about unused state vars.
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.
2025-05-19 00:33:06 +10:00

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.
%---------------------------------------------------------------------------%