Files
mercury/compiler/hlds_module.m
Zoltan Somogyi a32d6a16f4 Add the format_call pragma to the language.
doc/reference_manual.texi:
NEWS:
    Document and announce the new pragma.

compiler/prog_data_pragma.m:
compiler/prog_item.m:
    Provide a representation for the new pragma. The part that ends up
    being referred to from the HLDS goes into prog_data_pragma.m,
    the part that is not needed once the HLDS has been constructed
    goes into prog_item.m.

compiler/hlds_pred.m:
    Add a slot to pred_infos for info from the new pragma.

    Fix a bug in the comment on marker_has_format_call.

compiler/add_pragma.m:
    Add the information in these pragmas to the HLDS.

compiler/check_pragma_format_call.m:
    A new module to check the validity of format_call pragmas.
    These checks test whether the arguments named in such pragmas
    have the expected types and modes, which means that
    the check must be done after both type and mode checking.

compiler/check_hlds.m:
compiler/notes/compiler_design.html:
    Add and document the new module.

compiler/hlds_module.m:
    Add a field to the module_info that records the set of pred_ids
    that have format_call pragmas.

compiler/mercury_compile_front_end.m:
    Invoke the check_pragma_format_call pass *provided* that
    the new field in the module_info says it has any pragmas to check.

compiler/parse_pragma.m:
    Add code to parse the new pragma.

compiler/format_call.m:
    Check calls to predicates and functions with the new pragma
    the same way as we check calls to string.format, io.format,
    and stream.string_writer.format.

    This required separating the code that checked calls to such predicates
    from the code that optimized calls to such predicates, since

    - a predicate or function with a format_call pragma that specifies
      more than one argument pair has to have its correctness checked
      for each pair, and

    - a predicate or function with a format_call pragma does not actually
      do any formatting, so that formatting cannot be optimized.

    Fix an old bug, where we included the function result in the function's
    reported arity, which meant that an error message could mention a call
    to a nonexistent function. As part of that fix, the error message
    now specifies whether it is complaining about a call to a predicate
    or a function.

    Change the exported interface of this module a bit
    in order to allow the factoring out of repeated code.

compiler/parse_string_format.m:
    Separate the parsing of format strings from their optimization,
    again because calls to predicates and functions with format_call
    pragmas need to be checked but cannot be optimized.

compiler/polymorphism.m:
    Record the effect on argument numbers of any type_info and/or
    typeclass_info arguments added by this pass.

compiler/convert_parse_tree.m:
compiler/det_analysis.m:
compiler/direct_arg_in_out.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/hlds_out_pred.m:
compiler/item_util.m:
compiler/module_qual.qualify_items.m:
compiler/parse_tree_out_pragma.m:
compiler/prog_item_stats.m:
compiler/recompilation.version.m:
compiler/simplify_proc.m:
    Conform to the changes above.

tests/invalid/bad_format_call.{m,err_exp}:
    A new test case to see whether check_pragma_format_call.m detects
    and reports invalid format_call pragmas as expected.

tests/warnings/format_call_warning.{m,exp}:
tests/warnings/format_call_warning_helper.m:
    A new test case to see whether we generate the expected set of error
    messages for incorrect calls to a predicate with a format_call pragma.

tests/invalid/Mmakefile:
tests/warnings/Mercury.options:
tests/warnings/Mmakefile:
    Enable the new test cases.

tests/invalid/string_format_bad.err_exp:
tests/invalid/string_format_unknown.err_exp:
tests/warnings/disabled_warning.exp:
    Expect the predicate vs function distinction to the printed in
    error messages about bad calls to formatting predicates and functions.
2022-09-24 08:42:36 +10:00

1878 lines
80 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1996-2012 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: hlds_module.m.
% Main authors: fjh, conway.
%
% This module defines the main part of the High Level Data Structure or HLDS
% that deals with issues that concern the module as a whole.
%
% The main data structures defined here are the types
%
% module_info
%
% There is a separate interface section for each of these.
%
%---------------------------------------------------------------------------%
:- module hlds.hlds_module.
:- interface.
:- import_module analysis.
:- import_module check_hlds.
:- import_module check_hlds.proc_requests.
:- import_module hlds.const_struct.
:- import_module hlds.hlds_class.
:- import_module hlds.hlds_cons.
:- import_module hlds.hlds_data.
:- import_module hlds.hlds_dependency_graph.
:- import_module hlds.hlds_inst_mode.
:- import_module hlds.hlds_pred.
:- import_module hlds.hlds_promise.
:- import_module hlds.pred_table.
:- import_module hlds.special_pred.
:- import_module hlds.status.
:- import_module libs.
:- import_module libs.globals.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.
:- import_module parse_tree.module_qual.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_data_event.
:- import_module parse_tree.prog_data_foreign.
:- import_module parse_tree.prog_data_pragma.
:- import_module parse_tree.prog_data_used_modules.
:- import_module parse_tree.prog_foreign.
:- import_module parse_tree.prog_item.
:- import_module recompilation.
:- import_module cord.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module multi_map.
:- import_module one_or_more.
:- import_module pair.
:- import_module set.
:- import_module set_tree234.
%---------------------------------------------------------------------------%
%
% The module_info contains many fields of many types. These are the types
% that are not defined elsewhere.
%
:- type module_info.
:- type pragma_exported_proc
---> pragma_exported_proc(
foreign_language, % The language we are exporting to.
pred_id,
proc_id,
string, % The exported name of the procedure.
% i.e. the function name in C, method
% name in Java etc.
prog_context
).
% This structure contains the information we need to generate
% a type_ctor_info structure for a type defined in this module.
:- type type_ctor_gen_info
---> type_ctor_gen_info(
type_ctor,
module_name, % module name
string, % type name
int, % type arity
type_status, % status of the type
hlds_type_defn, % defn of type
pred_proc_id, % unify procedure
pred_proc_id % compare procedure
% maybe(pred_proc_id) % prettyprinter, if relevant
).
% Map from proc to a list of unused argument numbers.
%
:- type unused_arg_info == map(pred_proc_id, list(int)).
% For every procedure that requires its own tabling structure,
% this field records the information needed to define that structure.
:- type table_struct_map == map(pred_proc_id, table_struct_info).
:- type table_struct_info
---> table_struct_info(
table_struct_proc :: proc_table_struct_info,
table_struct_attrs :: table_attributes
).
% List of procedures for which there are user-requested type
% specializations, and a list of predicates which should be processed
% by higher_order.m to ensure the production of those versions.
:- type type_spec_info
---> type_spec_info(
% Procedures for which there are user-requested type
% specializations.
user_req_procs :: set(pred_proc_id),
% Set of predicates which need to be processed by
% higher_order.m to produce those specialized versions.
must_process_preds :: set(pred_id),
% Map from predicates for which the user requested a type
% specialization to the list of predicates which must be
% processed by higher_order.m to force the production of those
% versions. This is used by dead_proc_elim.m to avoid creating
% versions unnecessarily for versions in imported modules.
user_to_process_map :: multi_map(pred_id, pred_id),
% Type spec pragmas to be placed in the `.opt' file if a
% predicate becomes exported.
pragma_map :: multi_map(pred_id,
pragma_info_type_spec)
).
% Once filled in by simplify_proc.m (for all non-lambda procedures)
% and by lambda.m (for procedures created to implement lambda expressions),
% this map should have an entry for every procedure that is of interest to
% direct_arg_in_out.m. A procedure may be of interest to that module
% because it has one or more arguments that it needs to clone,
% or because it has one or more arguments whose modes do not specify
% whether they need to be cloned, and for which therefore it should
% generate a "sorry, not implemented" message. In both cases, the
% one_or_more(int) specify the argument positions involved; in the latter
% case, we also record the list of arguments for which we *could* tell
% they need to be cloned.
%
:- type direct_arg_proc_map == map(pred_proc_id, direct_arg_proc).
:- type direct_arg_proc
---> direct_arg_clone_proc(
clone_daio_args :: one_or_more(int)
)
; direct_arg_problem_proc(
problem_args :: one_or_more(int),
no_problem_args :: list(int)
).
% Maps the full names of procedures (in the sense of complexity_proc_name
% in complexity.m) to the number of their slot in MR_complexity_proc_table.
:- type complexity_proc_map == map(string, int).
:- type complexity_proc_info
---> complexity_proc_info(
% The index of the procedure in the runtime system's
% MR_complexity_procs array.
complexity_proc_num :: int,
% The full name of the procedure, in the form
% fqn/arity-modenum, where fqn is the predicate or function's
% fully qualified name.
complexity_proc_name :: string,
complexity_proc_args :: list(complexity_arg_info)
).
:- type complexity_arg_info
---> complexity_arg_info(
complexity_arg_name :: maybe(string),
complexity_arg_kind :: complexity_arg_kind
).
:- type complexity_arg_kind
---> complexity_input_variable_size
; complexity_input_fixed_size
; complexity_output.
:- type exported_enum_info
---> exported_enum_info(
% The type whose constants we are exporting to a foreign
% language.
eei_type_ctor :: type_ctor,
% The constants we are exporting.
eei_constants :: list(constructor_repn),
% The language we are exporting to.
eei_language :: foreign_language,
% This maps the names of the constructors in the Mercury type
% to their names in the foreign language.
eei_name_map :: map(string, string),
% The context of the foreign_export_enum pragma
% that asked for all this.
eei_context :: prog_context
).
:- type proc_analysis_kind
---> pak_exception
; pak_trailing
; pak_mm_tabling
; pak_termination
; pak_termination2
; pak_structure_sharing
; pak_structure_reuse.
% Types for order-independent state update (oisu).
%
:- type oisu_map == map(type_ctor, oisu_preds).
:- type oisu_preds
---> oisu_preds(
op_creators :: list(pred_id),
op_mutators :: list(pred_id),
op_destructors :: list(pred_id)
).
%---------------------------------------------------------------------------%
%
% The initialization predicate for the module_info data structure,
% and its raw getter and setter predicates.
%
% Create an empty module_info for the module named in the given
% compilation unit.
%
:- pred module_info_init(globals::in, module_name::in, prog_context::in,
string::in, include_module_map::in, used_modules::in, set(module_name)::in,
partial_qualifier_info::in, maybe(recompilation_info)::in,
type_repn_decision_data::in, module_info::out) is det.
% Once the module_info has been built, we call module_info_optimize
% to attempt to optimize the data structures for lots of accesses
% and relatively few insertion/deletions. This was useful when
% we stored maps using not-necessarily-balanced binary trees;
% this was when we balanced them. Now that we store maps in 234-trees,
% it is a no-op. However, we keep this predicate around, since we may
% yet switch to newer data structures that could also benefit from
% knowing when their access patterns change from mostly-write to
% mostly read. For example, we could switch some tables from
% 234-trees to arrays.
%
:- pred module_info_optimize(module_info::in, module_info::out) is det.
:- type avail_module_map == map(module_name, avail_module_entry).
:- type avail_module_entry
---> avail_module_entry(
% ms_interface iff any avail_module has ms_interface.
module_section,
% import_decl iff any avail_module has import_decl.
% XXX CLEANUP This is wrong. A module may have
% a ":- use_module" declaration in the interface and
% an ":- import_module" declaration in the implementation,
% and this design cannot express that.
import_or_use,
% The locations of the *explicit* import_module and
% use_import declarations, in the *source* of the module.
% The implicit ones aren't in the list, and neither
% are the imports and uses read in from interface
% and optimization files, so it is possible for the list
% to be empty.
list(avail_module)
).
:- type avail_module
---> avail_module(
module_section,
import_or_use,
prog_context
).
% The getter predicates. Please keep the order of declarations here
% and the order of the clauses below in sync with the order of the
% fields in the module_info and module_sub_info types.
:- pred module_info_get_globals(module_info::in, globals::out) is det.
:- pred module_info_get_predicate_table(module_info::in,
predicate_table::out) is det.
:- pred module_info_get_type_table(module_info::in, type_table::out) is det.
:- pred module_info_get_no_tag_types(module_info::in,
no_tag_type_table::out) is det.
:- pred module_info_get_inst_table(module_info::in, inst_table::out) is det.
:- pred module_info_get_mode_table(module_info::in, mode_table::out) is det.
:- pred module_info_get_cons_table(module_info::in, cons_table::out) is det.
:- pred module_info_get_ctor_field_table(module_info::in,
ctor_field_table::out) is det.
:- pred module_info_get_special_pred_maps(module_info::in,
special_pred_maps::out) is det.
:- pred module_info_get_class_table(module_info::in, class_table::out) is det.
:- pred module_info_get_instance_table(module_info::in,
instance_table::out) is det.
:- pred module_info_get_type_spec_info(module_info::in,
type_spec_info::out) is det.
:- pred module_info_get_const_struct_db(module_info::in,
const_struct_db::out) is det.
:- pred module_info_get_c_j_cs_fims(module_info::in,
c_j_cs_fims::out) is det.
:- pred module_info_get_pragma_exported_procs(module_info::in,
cord(pragma_exported_proc)::out) is det.
:- pred module_info_get_name(module_info::in, module_name::out) is det.
:- pred module_info_get_name_context(module_info::in,
prog_context::out) is det.
:- pred module_info_get_dump_hlds_base_file_name(module_info::in,
string::out) is det.
:- pred module_info_get_include_module_map(module_info::in,
include_module_map::out) is det.
:- pred module_info_get_partial_qualifier_info(module_info::in,
partial_qualifier_info::out) is det.
:- pred module_info_get_maybe_recompilation_info(module_info::in,
maybe(recompilation_info)::out) is det.
:- pred module_info_get_proc_requests(module_info::in,
proc_requests::out) is det.
:- pred module_info_get_assertion_table(module_info::in,
assertion_table::out) is det.
:- pred module_info_get_exclusive_table(module_info::in,
exclusive_table::out) is det.
:- pred module_info_get_has_parallel_conj(module_info::in,
has_parallel_conj::out) is det.
:- pred module_info_get_has_user_event(module_info::in,
has_user_event::out) is det.
:- pred module_info_get_direct_arg_proc_map(module_info::in,
direct_arg_proc_map::out) is det.
:- pred module_info_get_foreign_decl_codes_user(module_info::in,
cord(foreign_decl_code)::out) is det.
:- pred module_info_get_foreign_decl_codes_aux(module_info::in,
cord(foreign_decl_code)::out) is det.
:- pred module_info_get_foreign_body_codes(module_info::in,
cord(foreign_body_code)::out) is det.
:- pred module_info_get_fact_table_file_names(module_info::in,
list(string)::out) is det.
:- pred module_info_get_int_bad_clauses(module_info::in,
set(pred_pf_name_arity)::out) is det.
:- pred module_info_get_maybe_dependency_info(module_info::in,
maybe(hlds_dependency_info)::out) is det.
:- pred module_info_get_type_ctor_gen_infos(module_info::in,
list(type_ctor_gen_info)::out) is det.
:- pred module_info_get_must_be_stratified_preds(module_info::in,
set(pred_id)::out) is det.
:- pred module_info_get_unused_arg_info(module_info::in,
unused_arg_info::out) is det.
:- pred module_info_get_table_struct_map(module_info::in,
table_struct_map::out) is det.
:- pred module_info_get_avail_module_map(module_info::in,
avail_module_map::out) is det.
:- pred module_info_get_used_modules(module_info::in,
used_modules::out) is det.
:- pred module_info_get_ancestor_avail_modules(module_info::in,
set(module_name)::out) is det.
:- pred module_info_get_maybe_complexity_proc_map(module_info::in,
maybe(pair(int, complexity_proc_map))::out) is det.
:- pred module_info_get_complexity_proc_infos(module_info::in,
list(complexity_proc_info)::out) is det.
:- pred module_info_get_proc_analysis_kinds(module_info::in,
set(proc_analysis_kind)::out) is det.
:- pred module_info_get_analysis_info(module_info::in,
analysis_info::out) is det.
:- pred module_info_get_user_init_pred_target_names(module_info::in,
pred_target_names::out) is det.
:- pred module_info_get_user_final_pred_target_names(module_info::in,
pred_target_names::out) is det.
:- pred module_info_get_structure_reuse_preds(module_info::in,
set(pred_id)::out) is det.
:- pred module_info_get_format_call_pragma_preds(module_info::in,
set(pred_id)::out) is det.
:- pred module_info_get_exported_enums(module_info::in,
list(exported_enum_info)::out) is det.
:- pred module_info_get_event_set(module_info::in, event_set::out) is det.
:- pred module_info_get_oisu_map(module_info::in, oisu_map::out) is det.
:- pred module_info_get_oisu_procs(module_info::in,
set(pred_proc_id)::out) is det.
:- pred module_info_get_ts_rev_string_table(module_info::in, int::out,
list(string)::out) is det.
:- pred module_info_get_type_repn_dec(module_info::in,
type_repn_decision_data::out) is det.
% The setter predicates. Please keep the order of declarations here
% and the order of the clauses below in sync with the order of the
% fields in the module_info and module_sub_info types.
:- pred module_info_set_globals(globals::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_predicate_table(predicate_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_type_table(type_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_no_tag_types(no_tag_type_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_inst_table(inst_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_mode_table(mode_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_cons_table(cons_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_ctor_field_table(ctor_field_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_special_pred_maps(special_pred_maps::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_class_table(class_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_instance_table(instance_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_type_spec_info(type_spec_info::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_const_struct_db(const_struct_db::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_c_j_cs_fims(c_j_cs_fims::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_pragma_exported_procs(cord(pragma_exported_proc)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_maybe_recompilation_info(maybe(recompilation_info)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_proc_requests(proc_requests::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_assertion_table(assertion_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_exclusive_table(exclusive_table::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_has_parallel_conj(
module_info::in, module_info::out) is det.
:- pred module_info_set_has_user_event(
module_info::in, module_info::out) is det.
:- pred module_info_set_direct_arg_proc_map(direct_arg_proc_map::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_foreign_decl_codes_user(cord(foreign_decl_code)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_foreign_decl_codes_aux(cord(foreign_decl_code)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_foreign_body_codes(cord(foreign_body_code)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_int_bad_clauses(set(pred_pf_name_arity)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_type_ctor_gen_infos(list(type_ctor_gen_info)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_must_be_stratified_preds(set(pred_id)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_unused_arg_info(unused_arg_info::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_table_struct_map(table_struct_map::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_used_modules(used_modules::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_ancestor_avail_modules(set(module_name)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_maybe_complexity_proc_map(
maybe(pair(int, complexity_proc_map))::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_complexity_proc_infos(list(complexity_proc_info)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_proc_analysis_kinds(set(proc_analysis_kind)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_analysis_info(analysis_info::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_user_init_pred_target_names(pred_target_names::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_user_final_pred_target_names(pred_target_names::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_structure_reuse_preds(set(pred_id)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_format_call_pragma_preds(set(pred_id)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_exported_enums(list(exported_enum_info)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_event_set(event_set::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_oisu_map(oisu_map::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_oisu_procs(set(pred_proc_id)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_ts_rev_string_table(int::in, list(string)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_type_repn_dec(type_repn_decision_data::in,
module_info::in, module_info::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
% Utility predicates that are a bit more complicated than
% a simple getter or setter predicates.
%
:- pred module_info_get_pred_id_table(module_info::in,
pred_id_table::out) is det.
:- pred module_info_set_pred_id_table(pred_id_table::in,
module_info::in, module_info::out) is det.
% Given a pred_id, return the pred_info of the specified pred.
%
:- pred module_info_pred_info(module_info::in, pred_id::in, pred_info::out)
is det.
% Given a pred_proc_id, return the proc_info of the specified procedure.
%
:- pred module_info_proc_info(module_info::in, pred_proc_id::in,
proc_info::out) is det.
:- pred module_info_proc_info(module_info::in, pred_id::in, proc_id::in,
proc_info::out) is det.
% Given a pred_id and a proc_id, get the pred_info of that predicate
% and the proc_info for that mode of that predicate.
%
:- pred module_info_pred_proc_info(module_info::in, pred_id::in, proc_id::in,
pred_info::out, proc_info::out) is det.
:- pred module_info_pred_proc_info(module_info::in, pred_proc_id::in,
pred_info::out, proc_info::out) is det.
% Return a set of the pred_ids of all the valid predicates.
% Predicates whose definition contains a type error, etc.
% get removed from this set, so that later passes can rely
% on the predicates in this set being type-correct, etc.
%
:- pred module_info_get_valid_pred_id_set(module_info::in,
set_tree234(pred_id)::out) is det.
% Return the same pred_ids as module_info_get_valid_pred_id_set,
% but in the form of a sorted list.
%
:- pred module_info_get_valid_pred_ids(module_info::in,
list(pred_id)::out) is det.
% Remove one or more predicates from the set of valid pred_ids,
% to prevent further processing of those predicates after errors
% have been encountered in them.
%
:- pred module_info_make_pred_id_invalid(pred_id::in,
module_info::in, module_info::out) is det.
:- pred module_info_make_pred_ids_invalid(list(pred_id)::in,
module_info::in, module_info::out) is det.
% Completely remove a predicate from a module.
%
:- pred module_info_remove_predicate(pred_id::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_pred_info(pred_id::in, pred_info::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_pred_proc_info(pred_proc_id::in,
pred_info::in, proc_info::in, module_info::in, module_info::out) is det.
:- pred module_info_set_pred_proc_info(pred_id::in, proc_id::in,
pred_info::in, proc_info::in, module_info::in, module_info::out) is det.
%---------------------%
:- pred predicate_id(module_info::in, pred_id::in, module_name::out,
string::out, arity::out) is det.
:- func predicate_module(module_info, pred_id) = module_name.
:- func predicate_name(module_info, pred_id) = string.
:- func predicate_arity(module_info, pred_id) = arity.
%---------------------%
:- pred module_add_foreign_decl_code_user(foreign_decl_code::in,
module_info::in, module_info::out) is det.
:- pred module_add_foreign_decl_code_aux(foreign_decl_code::in,
module_info::in, module_info::out) is det.
:- pred module_add_foreign_body_code(foreign_body_code::in,
module_info::in, module_info::out) is det.
:- pred module_add_item_fim(item_fim::in,
module_info::in, module_info::out) is det.
:- pred module_add_fact_table_file(string::in,
module_info::in, module_info::out) is det.
%---------------------%
% Please see module_info_ensure_dependency_info for the constraints
% on the returned dependency_info.
%
:- pred module_info_dependency_info(module_info::in,
hlds_dependency_info::out) is det.
:- pred module_info_set_dependency_info(hlds_dependency_info::in,
module_info::in, module_info::out) is det.
:- pred module_info_clobber_dependency_info(
module_info::in, module_info::out) is det.
%---------------------%
% The module_info stores a counter which is used to distinguish
% lambda predicates which appear on the same line in the same file.
% This predicate returns the next number for the given context
% and increments the counter for that context.
%
:- pred module_info_next_lambda_count(prog_context::in, int::out,
module_info::in, module_info::out) is det.
:- pred module_info_next_atomic_count(prog_context::in, int::out,
module_info::in, module_info::out) is det.
:- pred module_info_next_loop_inv_count(prog_context::in, int::out,
module_info::in, module_info::out) is det.
%---------------------%
:- pred module_add_avail_module_name(module_name::in,
module_section::in, import_or_use::in, maybe(prog_context)::in,
module_info::in, module_info::out) is det.
:- pred module_add_indirectly_imported_module_name(module_name::in,
module_info::in, module_info::out) is det.
% Return the set of the visible modules. These are
%
% (1) the current module,
% (2) any imported modules,
% (3) any ancestor modules, and
% (4) any modules imported by ancestor modules.
%
% It excludes transitively imported modules (those for which we read
% `.int2' files).
%
:- pred module_info_get_visible_modules(module_info::in,
set(module_name)::out) is det.
% This returns all the modules that this module's code depends on,
% i.e. all modules that have been used or imported by this module,
% directly or indirectly, including parent modules.
%
:- pred module_info_get_all_deps(module_info::in,
set(module_name)::out) is det.
:- pred module_info_add_module_to_public_used_modules(module_name::in,
module_info::in, module_info::out) is det.
%---------------------%
:- pred module_info_user_init_pred_target_names(module_info::in,
list(string)::out) is det.
:- pred module_info_user_final_pred_target_names(module_info::in,
list(string)::out) is det.
:- pred module_info_user_init_pred_procs(module_info::in,
list(pred_proc_id)::out) is det.
:- pred module_info_user_final_pred_procs(module_info::in,
list(pred_proc_id)::out) is det.
%---------------------------------------------------------------------------%
% The information needed by the pass that decides type representations.
% The first three fields contain information that it uses make its
% decisions; the fourth contains information that says what it should *do*
% with the results of its decisions.
%
:- type type_repn_decision_data
---> type_repn_decision_data(
% The contents of type_repn items read in from the interface
% files of other modules, containing information about the
% representations of the types defined in those modules.
trdd_type_repns :: type_ctor_repn_map,
% The contents of direct_arg clauses in type definitions
% read in from the interface files of other modules,
% containing information about the direct_arg part of the
% representations of those types.
%
% XXX TYPE_REPN In the future, this information should *also*
% be stored in type_repn items.
trdd_direct_arg_map :: direct_arg_map,
% The contents of foreign_enum pragmas read in either
% from interface files of other modules, or the source file
% of the module being compiled, giving the foreign language
% definition of a type.
trdd_foreign_enums :: list({item_mercury_status,
item_foreign_enum_info}),
% The contents of foreign_export_enum pragmas read in
% from the source file of the module being compiled,
% asking the compiler to generate definitions
% of the named types in the named foreign languages.
trdd_foreign_exports :: list(item_foreign_export_enum_info)
).
:- type direct_arg_map == map(type_ctor, list(sym_name_arity)).
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.op_mode.
:- import_module mdbcomp.builtin_modules.
:- import_module transform_hlds.
:- import_module transform_hlds.mmc_analysis.
:- import_module assoc_list.
:- import_module bool.
:- import_module counter.
:- import_module require.
:- import_module string.
% The module_info, module_sub_info and module_rare_info types
% constitute a single logical data structure split into three parts
% for efficiency purposes.
%
% The module_info type contains the most frequently accessed and updated
% pieces of information about the module.
%
% We keep the other pieces of information we need about the module
% in the module_sub_info or the module_rare_info types. Those that are
% reasonably frequently updated are in the module_sub_info; those that
% are rarely or never updated are in the module_rare_info.
%
% This arrangement minimizes the amount of memory that needs to be
% allocated, and filled in, when a field is updated.
%
% Note that a field may be rarely read or written for two main reasons.
%
% - One reason is that the compiler simply does not need to read or write
% the field very often. This may be e.g. because it is used only
% when processing a language construct that is rare, or because
% its uses are concentrated in a few pieces of code that read it
% only when they start and write it only when they finish.
%
% - Another reason is that it is used only when a compiler option
% is given, and it is rarely given.
% Please keep the order of the fields in module_info, module_sub_info
% and module_rare_info in sync with the order of the both the
% declarations and definitions of both the getter and setter predicates.
:- type module_info
---> module_info(
% The Boehm collector allocates blocks whose sizes are
% multiples of 2. Please keep the number of fields here
% to a multiple of 2 as well.
% Note that the no_tag_type_table contains information
% about notag types that is also available in the type_table,
% but in a format that allows faster access.
/* 01 */ mi_sub_info :: module_sub_info,
/* 02 */ mi_rare_info :: module_rare_info,
/* 03 */ mi_globals :: globals,
/* 04 */ mi_predicate_table :: predicate_table,
/* 05 */ mi_type_table :: type_table,
/* 06 */ mi_no_tag_type_table :: no_tag_type_table,
/* 07 */ mi_inst_table :: inst_table,
/* 08 */ mi_mode_table :: mode_table,
/* 09 */ mi_cons_table :: cons_table,
/* 10 */ mi_ctor_field_table :: ctor_field_table
).
:- type module_sub_info
---> module_sub_info(
msi_special_pred_maps :: special_pred_maps,
msi_class_table :: class_table,
msi_instance_table :: instance_table,
% Data used for user-guided type specialization.
msi_type_spec_info :: type_spec_info,
% The database of constant structures the code generator
% will generate independently, outside all the procedures
% of the program.
msi_const_struct_db :: const_struct_db,
msi_c_j_cs_fims :: c_j_cs_fims,
% List of the procs for which there is a
% pragma foreign_export(...) declaration.
msi_pragma_exported_procs :: cord(pragma_exported_proc)
).
:- type module_rare_info
---> module_rare_info(
mri_module_name :: module_name,
mri_module_name_context :: prog_context,
mri_dump_base_file_name :: string,
mri_include_module_map :: include_module_map,
mri_partial_qualifier_info :: partial_qualifier_info,
mri_maybe_recompilation_info :: maybe(recompilation_info),
mri_proc_requests :: proc_requests,
mri_assertion_table :: assertion_table,
mri_exclusive_table :: exclusive_table,
mri_direct_arg_proc_map :: direct_arg_proc_map,
mri_has_parallel_conj :: has_parallel_conj,
mri_has_user_event :: has_user_event,
% We classify foreign code fragments bodily included in the
% generated target language file into three categories,
% based on two criteria.
%
% The first criterion is declarations (decl_codes) vs
% non-declarations (body codes). We separate these because
% we have to put declarations before code that may use those
% declarations.
%
% We would prefer the second criterion to be declarations
% that define types vs declarations that define other entities
% that may refer to those types, such as global variables
% or function, again so that we can emit the former before
% the latter, Unfortunately, foreign_decl pragmas do not
% specify what they define. Instead, our second criterion is
% user-provided declarations vs aux declarations added
% by the Mercury compiler itself to implement either
% (a) mutables, or (b) fact tables. Neither of the latter
% define types, so putting these after user-provided
% declarations will work, as long as in the user-provided
% declarations, definitions of types precede definitions
% of other entities that refer to those types. Ensuring that
% is the programmer's responsibility.
mri_foreign_decl_codes_user :: cord(foreign_decl_code),
mri_foreign_decl_codes_aux :: cord(foreign_decl_code),
mri_foreign_body_codes :: cord(foreign_body_code),
% The names of the files containing fact tables implementing
% predicates defined in this module.
mri_fact_table_file_names :: list(string),
% The set of predicates and functions for which there was
% an attempt to define them in the interface (by clause,
% foreign_proc, or external_proc pragma), which means that
% if we find no definition for them in the implementation
% section either, we should NOT generate an error message
% complaining about the definition being missing. Such a
% message would be misleading, since the definition is not
% missing, it was just misplaced, and we have already
% generated an error message about that misplaced attempt
% at definition.
mri_int_bad_clauses :: set(pred_pf_name_arity),
% Please see module_info_ensure_dependency_info for the
% meaning of this dependency_info, and the constraints on it.
mri_maybe_dependency_info :: maybe(hlds_dependency_info),
mri_type_ctor_gen_infos :: list(type_ctor_gen_info),
mri_must_be_stratified_preds :: set(pred_id),
% Unused argument info about predicates in the current module
% which has been exported in .opt files.
mri_unused_arg_info :: unused_arg_info,
% For every procedure that requires its own tabling structure,
% this field records the information needed to define that
% structure.
mri_table_struct_map :: table_struct_map,
% How many lambda expressions there are at different contexts
% in the module. This is used to uniquely identify lambda
% expressions that appear on the same line of the same file.
mri_lambdas_per_context :: map(prog_context, counter),
% How many STM atomic expressions there are at different
% contexts in the module. This is used to uniquely identify
% STM atomic expressions that appear on the same line of
% the same file.
mri_atomics_per_context :: map(prog_context, counter),
% How many loop invariant optimizations we have done at
% different contexts in the module. This is used to provide
% a uniquely identify the predicates that we create
% using the loop invariant optimization, in the rare case
% that one line contains the definition of more than one
% predicate.
mri_loop_invs_per_context :: map(prog_context, counter),
% The add_item_avails predicate in make_hlds_passes.m fills
% this field with information about all the import- and
% use_module declarations both in the module being compiled,
% and in the .int0 interface files of its ancestors.
%
% Each entry in the avail_module_map will specify
%
% - whether the module is imported or used in the interface
% of either the module or its ancestors, and
%
% - whether the module is imported (as opposed to used)
% in either the module or its ancestors.
%
% Each entry will also contain a list of avail_modules
% *for import/use_module declarations in this module only*;
% there won't be any entries for imports/uses in ancestors.
%
% This field is used by:
%
% - intermod.m to (over-)estimate the set of use_module decls
% needed by the code put into a .opt file;
%
% - try_expand.m to see whether exception is imported
% and hence whether it has anything to do at all
% (since we import exception.m implicitly if some code
% contains a try goal);
%
% - by unused_imports.m to decide what import_module and/or
% use_module declarations to warn about;
%
% - by xml_documentation to prettyprint a module as XML;
%
% and possibly more.
mri_avail_module_map :: avail_module_map,
% The names of all the indirectly imported modules
% (used by the MLDS back-end).
%
% XXX CLEANUP The above is misleading.
% When added to the info in the previous field, the value
% in this field is used to for two purposes, both of which
% need the full set of modules imported and/or used both
% directly and indirectly, and both explicitly or implicitly.
% The purposes are:
%
% - #including those the .mh and .mih files of those modules;
% - reading and writing the .analysis files of those modules.
mri_indirectly_imported_module_names
:: set(module_name),
% The modules which have already been calculated as being used.
% This slot is initialized to the set of modules that have
% been seen to be used during the expansion of equivalence
% types and insts.
mri_used_modules :: used_modules,
% The set of modules imported by ancestor modules.
%
% We used to add these to mri_used_modules, but that prevented
% the compiler from generating useful warnings about unused
% local imports/uses of those modules. We now keep this info
% on a "may be useful later" basis; it is current unused.
mri_ancestor_avail_modules :: set(module_name),
% Information about the procedures we are performing
% complexity experiments on.
mri_maybe_complexity_proc_map :: maybe(pair(int,
complexity_proc_map)),
mri_complexity_proc_infos :: list(complexity_proc_info),
% Records the set of analyses whose results are now available
% in the proc_infos. As each analysis puts its results
% in the proc_infos, it should add its id to this set.
mri_proc_analysis_kinds :: set(proc_analysis_kind),
% Information for the inter-module analysis framework.
mri_analysis_info :: analysis_info,
% Exported target language names for preds appearing in
% `:- initialise' directives, and implicitly in
% `:- mutable' directives, in this module.
mri_user_init_pred_target_names :: pred_target_names,
% Exported target names for preds appearing in
% `:- finalise' directives in this module.
mri_user_final_pred_target_names :: pred_target_names,
% Predicates which were created as reuse versions of other
% procedures. Its only use is to avoid writing out pragmas
% for structure reuse predicates to `.trans_opt' files.
mri_structure_reuse_preds :: set(pred_id),
% The set of predicates in the HLDS that have
% a format_call pragma.
%
% This set is filled in by add_pragma.m when the HLDS
% is first constructed. Usually, this set will be empty,
% but if it is not, the check_pragma_format_call_preds pass
% will check all these pragmas for errors.
%
% This pass must be after type and mode analysis (since it
% needs to know the types and modes of procedure arguments),
% and must be before the simplification pass at the end of
% semantic analysis (since that is when format_call.m's code
% uses this info, relying on it having being checked).
mri_format_call_pragma_preds :: set(pred_id),
% Enumeration types that have been exported to a foreign
% language.
mri_exported_enums :: list(exported_enum_info),
mri_event_set :: event_set,
% The set of visible declarations about order-independent
% state update.
mri_oisu_map :: oisu_map,
% The set of procedures defined in this module that
% have OISU arguments.
mri_oisu_procs :: set(pred_proc_id),
% A table of strings used by some threadscope events.
% Currently threadscope events are introduced for each future
% in dep_par_conj.m which is why we need to record the table
% within the HLDS. The LLDS also uses threadscope string
% tables, see global_data.m, the LLDS introduces strings during
% the HLDS->LLDS transformation of parallel conjunctions.
mri_ts_string_table_size :: int,
mri_ts_rev_string_table :: list(string),
% Information needed to decide type representations.
mri_type_repn_dec :: type_repn_decision_data
).
% Access stats for the module_info structure on 30 december 2014.
%
% i read same diff same%
% 0 188233540 17 38369323 0.00% predicate_table
% 1 7933 0 480 0.00% proc_requests
% 2 261171 0 103230 0.00% special_pred_maps
% 3 4576898 0 0 partial_qualifier_info
% 4 21758620 2908 1589788 0.18% type_table
% 5 22754063 0 2360725 0.00% inst_table
% 6 145877431 10501 149637 6.56% mode_table
% 7 16110150 3767 803152 0.47% cons_table
% 8 7125765 353 65777 0.53% class_table
% 9 2543131 353 206012 0.17% instance_table
% 10 7935 0 3798 0.00% assertion_table
% 11 0 0 0 exclusive_table
% 12 4552293 620283 180042 77.50% ctor_field_table
% 13 2256146 2219707 235 99.99% maybe_recompilation_info
% 14 14893776 0 0 name
% 15 0 0 0 dump_hlds_base_file_name
% 16 39144524 0 16950 0.00% globals
% 17 8481 17 64 20.99% has_parallel_conj
% 18 253 4 5 44.44% has_user_event
% 19 0 223574 3371 98.51% contains_foreign_type
% 20 9180 0 710 0.00% foreign_decl_codes
% 21 3683 0 856 0.00% foreign_body_codes
% 22 966008 0 963108 0.00% foreign_import_modules
% 23 331870 281405 35898 88.69% pragma_exported_procs
% 24 1 0 0 fact_table_file_names
% 25 10630 11345 8490 57.20% maybe_dependency_info
% 26 11342 4885 128 97.45% num_errors
% 27 35292 2442 3209 43.21% type_ctor_gen_infos
% 28 3506 0 2 0.00% must_be_stratified_preds
% 29 1 0 1 0.00% unused_arg_info
% 30 3972001 0 3445467 0.00% exception_info
% 31 296 0 0 trailing_info
% 32 4071 0 75 0.00% table_struct_map
% 33 296 0 0 mm_tabling_info
% 34 4019 0 4019 0.00% lambdas_per_context
% 35 0 0 0 atomics_per_context
% 36 7053 0 0 imported_module_names
% 37 3135 0 0 indirectly_imported_mod_specs
% 38 1 0 0 interface_module_names
% 39 6568 0 3767 0.00% used_modules
% 40 1656135 0 126058 0.00% type_spec_info
% 41 22588003 0 87106 0.00% no_tag_types
% 42 171993 0 0 complexity_proc_map
% 43 2821 0 0 complexity_proc_infos
% 44 763 336 2 99.41% analysis_info
% 45 316 0 20 0.00% structure_reuse_preds
% 46 5703 0 55 0.00% exported_enums
% 47 48 0 3767 0.00% event_set
% 48 3510 0 6 0.00% oisu_map
% 49 0 0 2 0.00% oisu_procs
% 50 2684695 2592456 10222 99.61% const_struct_db
% 51 2821 0 0 threadscope_string_table
%---------------------------------------------------------------------------%
module_info_init(Globals, ModuleName, ModuleNameContext, DumpBaseFileName,
InclMap, UsedModules, ImplicitlyUsedModules,
QualifierInfo, MaybeRecompInfo, TypeRepnDec, ModuleInfo) :-
SpecialPredMaps = special_pred_maps(map.init, map.init, map.init),
map.init(ClassTable),
map.init(InstanceTable),
set.init(TypeSpecPreds),
set.init(TypeSpecForcePreds),
map.init(SpecMap),
map.init(PragmaMap),
TypeSpecInfo = type_spec_info(TypeSpecPreds, TypeSpecForcePreds,
SpecMap, PragmaMap),
const_struct_db_init(Globals, ConstStructDb),
ForeignImportModules = init_foreign_import_modules,
PragmaExportedProcs = cord.init,
ModuleSubInfo = module_sub_info(
SpecialPredMaps,
ClassTable,
InstanceTable,
TypeSpecInfo,
ConstStructDb,
ForeignImportModules,
PragmaExportedProcs),
init_requests(ProcRequests),
assertion_table_init(AssertionTable),
exclusive_table_init(ExclusiveTable),
map.init(DirectArgInOutMap),
HasParallelConj = has_no_parallel_conj,
HasUserEvent = has_no_user_event,
ForeignDeclsUser = cord.init,
ForeignDeclsAux = cord.init,
ForeignBodies = cord.init,
FactTableFiles = [],
set.init(IntBadPreds),
MaybeDependencyInfo = maybe.no,
MustBeStratifiedPreds = [],
set.init(StratPreds),
map.init(UnusedArgInfo),
map.init(TablingStructMap),
map.init(LambdasPerContext),
map.init(AtomicsPerContext),
map.init(LoopInvsPerContext),
% XXX ITEM_LIST Given that we start with an aug_compilation_unit,
% shouldn't the work of finding implicit dependencies have already
% been done?
% XXX ITEM_LIST Should a tabled predicate declared in a .int* or .*opt
% file generate an implicit dependency?
% XXX ITEM_LIST We should record ImportDeps and UseDeps separately.
% XXX ITEM_LIST Should we record implicitly and explicitly imported
% separately, or at least record for each import (and use) whether
% it was explicit or implicit, and one (or more) context where either
% the explicit imported was requested, or the implicit import was required.
map.init(AvailModuleMap0),
add_implicit_avail_module(import_decl, mercury_public_builtin_module,
AvailModuleMap0, AvailModuleMap1),
set.fold(add_implicit_avail_module(use_decl), ImplicitlyUsedModules,
AvailModuleMap1, AvailModuleMap),
set.init(IndirectlyImportedModules),
set.init(AncestorAvailModules),
MaybeComplexityMap = no,
ComplexityProcInfos = [],
set.init(ProcAnalysisKinds),
globals.get_op_mode(Globals, OpMode),
( if OpMode = opm_top_args(opma_augment(opmau_make_analysis_registry)) then
MakeAnalysisReg = yes
else
MakeAnalysisReg = no
),
AnalysisInfo = init_analysis_info(mmc, ModuleName, MakeAnalysisReg),
UserInitPredTargetNames = pred_target_names(map.init),
UserFinalPredTargetNames = pred_target_names(map.init),
set.init(StructureReusePredIds),
set.init(FormatCallPragmaPredIds),
ExportedEnums = [],
EventSet = event_set("", map.init),
map.init(OISUMap),
set.init(OISUProcs),
TSStringTableSize = 0,
TSRevStringTable = [],
ModuleRareInfo = module_rare_info(
ModuleName,
ModuleNameContext,
DumpBaseFileName,
InclMap,
QualifierInfo,
MaybeRecompInfo,
ProcRequests,
AssertionTable,
ExclusiveTable,
DirectArgInOutMap,
HasParallelConj,
HasUserEvent,
ForeignDeclsUser,
ForeignDeclsAux,
ForeignBodies,
FactTableFiles,
IntBadPreds,
MaybeDependencyInfo,
MustBeStratifiedPreds,
StratPreds,
UnusedArgInfo,
TablingStructMap,
LambdasPerContext,
AtomicsPerContext,
LoopInvsPerContext,
AvailModuleMap,
IndirectlyImportedModules,
UsedModules,
AncestorAvailModules,
MaybeComplexityMap,
ComplexityProcInfos,
ProcAnalysisKinds,
AnalysisInfo,
UserInitPredTargetNames,
UserFinalPredTargetNames,
StructureReusePredIds,
FormatCallPragmaPredIds,
ExportedEnums,
EventSet,
OISUMap,
OISUProcs,
TSStringTableSize,
TSRevStringTable,
TypeRepnDec),
predicate_table_init(PredicateTable),
TypeTable = init_type_table,
map.init(NoTagTypes),
inst_table_init(InstTable),
mode_table_init(ModeTable),
CtorTable = init_cons_table,
map.init(FieldNameTable),
ModuleInfo = module_info(
ModuleSubInfo,
ModuleRareInfo,
Globals,
PredicateTable,
TypeTable,
NoTagTypes,
InstTable,
ModeTable,
CtorTable,
FieldNameTable).
:- pred add_implicit_avail_module(import_or_use::in, module_name::in,
avail_module_map::in, avail_module_map::out) is det.
add_implicit_avail_module(ImportOrUse, ModuleName, !AvailModuleMap) :-
Entry = avail_module_entry(ms_implementation, ImportOrUse, []),
map.det_insert(ModuleName, Entry, !AvailModuleMap).
module_info_optimize(!ModuleInfo) :-
% Currently, all the calls to *_table_optimize are no-ops.
% We keep them, and this predicate, in case that changes in the future.
module_info_get_predicate_table(!.ModuleInfo, Preds0),
predicate_table_optimize(Preds0, Preds),
module_info_set_predicate_table(Preds, !ModuleInfo),
module_info_get_inst_table(!.ModuleInfo, InstTable0),
inst_table_get_user_insts(InstTable0, UserInstTable0),
map.optimize(UserInstTable0, UserInstTable),
inst_table_set_user_insts(UserInstTable, InstTable0, InstTable),
module_info_set_inst_table(InstTable, !ModuleInfo),
module_info_get_mode_table(!.ModuleInfo, Modes0),
mode_table_optimize(Modes0, Modes),
module_info_set_mode_table(Modes, !ModuleInfo),
module_info_get_cons_table(!.ModuleInfo, Ctors0),
cons_table_optimize(Ctors0, Ctors),
module_info_set_cons_table(Ctors, !ModuleInfo).
%---------------------------------------------------------------------------%
%
% Getter and setter predicates on the module_info that are local to this
% module.
%
:- pred module_info_get_lambdas_per_context(module_info::in,
map(prog_context, counter)::out) is det.
:- pred module_info_get_atomics_per_context(module_info::in,
map(prog_context, counter)::out) is det.
:- pred module_info_get_loop_invs_per_context(module_info::in,
map(prog_context, counter)::out) is det.
:- pred module_info_get_indirectly_imported_module_names(module_info::in,
set(module_name)::out) is det.
:- pred module_info_set_maybe_dependency_info(maybe(hlds_dependency_info)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_lambdas_per_context(map(prog_context, counter)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_atomics_per_context(map(prog_context, counter)::in,
module_info::in, module_info::out) is det.
:- pred module_info_set_loop_invs_per_context(map(prog_context, counter)::in,
module_info::in, module_info::out) is det.
%---------------------------------------------------------------------------%
%
% Getter predicates for the module_info.
%
module_info_get_globals(MI, X) :-
X = MI ^ mi_globals.
module_info_get_predicate_table(MI, X) :-
X = MI ^ mi_predicate_table.
module_info_get_type_table(MI, X) :-
X = MI ^ mi_type_table.
module_info_get_no_tag_types(MI, X) :-
X = MI ^ mi_no_tag_type_table.
module_info_get_inst_table(MI, X) :-
X = MI ^ mi_inst_table.
module_info_get_mode_table(MI, X) :-
X = MI ^ mi_mode_table.
module_info_get_cons_table(MI, X) :-
X = MI ^ mi_cons_table.
module_info_get_ctor_field_table(MI, X) :-
X = MI ^ mi_ctor_field_table.
module_info_get_special_pred_maps(MI, X) :-
X = MI ^ mi_sub_info ^ msi_special_pred_maps.
module_info_get_class_table(MI, X) :-
X = MI ^ mi_sub_info ^ msi_class_table.
module_info_get_instance_table(MI, X) :-
X = MI ^ mi_sub_info ^ msi_instance_table.
module_info_get_type_spec_info(MI, X) :-
X = MI ^ mi_sub_info ^ msi_type_spec_info.
module_info_get_const_struct_db(MI, X) :-
X = MI ^ mi_sub_info ^ msi_const_struct_db.
module_info_get_c_j_cs_fims(MI, X) :-
X = MI ^ mi_sub_info ^ msi_c_j_cs_fims.
module_info_get_pragma_exported_procs(MI, X) :-
X = MI ^ mi_sub_info ^ msi_pragma_exported_procs.
module_info_get_name(MI, X) :-
X = MI ^ mi_rare_info ^ mri_module_name.
module_info_get_name_context(MI, X) :-
X = MI ^ mi_rare_info ^ mri_module_name_context.
module_info_get_dump_hlds_base_file_name(MI, X) :-
X = MI ^ mi_rare_info ^ mri_dump_base_file_name.
module_info_get_include_module_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_include_module_map.
module_info_get_partial_qualifier_info(MI, X) :-
X = MI ^ mi_rare_info ^ mri_partial_qualifier_info.
module_info_get_maybe_recompilation_info(MI, X) :-
X = MI ^ mi_rare_info ^ mri_maybe_recompilation_info.
module_info_get_proc_requests(MI, X) :-
X = MI ^ mi_rare_info ^ mri_proc_requests.
module_info_get_assertion_table(MI, X) :-
X = MI ^ mi_rare_info ^ mri_assertion_table.
module_info_get_exclusive_table(MI, X) :-
X = MI ^ mi_rare_info ^ mri_exclusive_table.
module_info_get_has_parallel_conj(MI, X) :-
X = MI ^ mi_rare_info ^ mri_has_parallel_conj.
module_info_get_has_user_event(MI, X) :-
X = MI ^ mi_rare_info ^ mri_has_user_event.
module_info_get_direct_arg_proc_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_direct_arg_proc_map.
module_info_get_foreign_decl_codes_user(MI, X) :-
X = MI ^ mi_rare_info ^ mri_foreign_decl_codes_user.
module_info_get_foreign_decl_codes_aux(MI, X) :-
X = MI ^ mi_rare_info ^ mri_foreign_decl_codes_aux.
module_info_get_foreign_body_codes(MI, X) :-
X = MI ^ mi_rare_info ^ mri_foreign_body_codes.
module_info_get_fact_table_file_names(MI, X) :-
X = MI ^ mi_rare_info ^ mri_fact_table_file_names.
module_info_get_int_bad_clauses(MI, X) :-
X = MI ^ mi_rare_info ^ mri_int_bad_clauses.
module_info_get_maybe_dependency_info(MI, X) :-
X = MI ^ mi_rare_info ^ mri_maybe_dependency_info.
module_info_get_type_ctor_gen_infos(MI, X) :-
X = MI ^ mi_rare_info ^ mri_type_ctor_gen_infos.
module_info_get_must_be_stratified_preds(MI, X) :-
X = MI ^ mi_rare_info ^ mri_must_be_stratified_preds.
module_info_get_unused_arg_info(MI, X) :-
X = MI ^ mi_rare_info ^ mri_unused_arg_info.
module_info_get_table_struct_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_table_struct_map.
module_info_get_lambdas_per_context(MI, X) :-
X = MI ^ mi_rare_info ^ mri_lambdas_per_context.
module_info_get_atomics_per_context(MI, X) :-
X = MI ^ mi_rare_info ^ mri_atomics_per_context.
module_info_get_loop_invs_per_context(MI, X) :-
X = MI ^ mi_rare_info ^ mri_loop_invs_per_context.
module_info_get_avail_module_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_avail_module_map.
module_info_get_indirectly_imported_module_names(MI, X) :-
X = MI ^ mi_rare_info ^ mri_indirectly_imported_module_names.
module_info_get_used_modules(MI, X) :-
X = MI ^ mi_rare_info ^ mri_used_modules.
module_info_get_ancestor_avail_modules(MI, X) :-
X = MI ^ mi_rare_info ^ mri_ancestor_avail_modules.
module_info_get_maybe_complexity_proc_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_maybe_complexity_proc_map.
module_info_get_complexity_proc_infos(MI, X) :-
X = MI ^ mi_rare_info ^ mri_complexity_proc_infos.
module_info_get_proc_analysis_kinds(MI, X) :-
X = MI ^ mi_rare_info ^ mri_proc_analysis_kinds.
module_info_get_analysis_info(MI, X) :-
X = MI ^ mi_rare_info ^ mri_analysis_info.
module_info_get_user_init_pred_target_names(MI, X) :-
X = MI ^ mi_rare_info ^ mri_user_init_pred_target_names.
module_info_get_user_final_pred_target_names(MI, X) :-
X = MI ^ mi_rare_info ^ mri_user_final_pred_target_names.
module_info_get_structure_reuse_preds(MI, X) :-
X = MI ^ mi_rare_info ^ mri_structure_reuse_preds.
module_info_get_format_call_pragma_preds(MI, X) :-
X = MI ^ mi_rare_info ^ mri_format_call_pragma_preds.
module_info_get_exported_enums(MI, X) :-
X = MI ^ mi_rare_info ^ mri_exported_enums.
module_info_get_event_set(MI, X) :-
X = MI ^ mi_rare_info ^ mri_event_set.
module_info_get_oisu_map(MI, X) :-
X = MI ^ mi_rare_info ^ mri_oisu_map.
module_info_get_oisu_procs(MI, X) :-
X = MI ^ mi_rare_info ^ mri_oisu_procs.
module_info_get_ts_rev_string_table(MI, X, Y) :-
X = MI ^ mi_rare_info ^ mri_ts_string_table_size,
Y = MI ^ mi_rare_info ^ mri_ts_rev_string_table.
module_info_get_type_repn_dec(MI, X) :-
X = MI ^ mi_rare_info ^ mri_type_repn_dec.
%---------------------------------------------------------------------------%
%
% Setter predicates for the module_info.
%
module_info_set_globals(X, !MI) :-
!MI ^ mi_globals := X.
module_info_set_predicate_table(X, !MI) :-
!MI ^ mi_predicate_table := X.
module_info_set_type_table(X, !MI) :-
!MI ^ mi_type_table := X.
module_info_set_no_tag_types(X, !MI) :-
!MI ^ mi_no_tag_type_table := X.
module_info_set_inst_table(X, !MI) :-
!MI ^ mi_inst_table := X.
module_info_set_mode_table(X, !MI) :-
!MI ^ mi_mode_table := X.
module_info_set_cons_table(X, !MI) :-
!MI ^ mi_cons_table := X.
module_info_set_ctor_field_table(X, !MI) :-
!MI ^ mi_ctor_field_table := X.
module_info_set_special_pred_maps(X, !MI) :-
!MI ^ mi_sub_info ^ msi_special_pred_maps := X.
module_info_set_class_table(X, !MI) :-
!MI ^ mi_sub_info ^ msi_class_table := X.
module_info_set_instance_table(X, !MI) :-
!MI ^ mi_sub_info ^ msi_instance_table := X.
module_info_set_type_spec_info(X, !MI) :-
!MI ^ mi_sub_info ^ msi_type_spec_info := X.
module_info_set_const_struct_db(X, !MI) :-
( if
private_builtin.pointer_equal(X,
!.MI ^ mi_sub_info ^ msi_const_struct_db)
then
true
else
!MI ^ mi_sub_info ^ msi_const_struct_db := X
).
module_info_set_c_j_cs_fims(X, !MI) :-
!MI ^ mi_sub_info ^ msi_c_j_cs_fims := X.
module_info_set_pragma_exported_procs(X, !MI) :-
( if
private_builtin.pointer_equal(X,
!.MI ^ mi_sub_info ^ msi_pragma_exported_procs)
then
true
else
!MI ^ mi_sub_info ^ msi_pragma_exported_procs := X
).
module_info_set_maybe_recompilation_info(X, !MI) :-
( if
private_builtin.pointer_equal(X,
!.MI ^ mi_rare_info ^ mri_maybe_recompilation_info)
then
true
else
!MI ^ mi_rare_info ^ mri_maybe_recompilation_info := X
).
module_info_set_proc_requests(X, !MI) :-
!MI ^ mi_rare_info ^ mri_proc_requests := X.
module_info_set_assertion_table(X, !MI) :-
!MI ^ mi_rare_info ^ mri_assertion_table := X.
module_info_set_exclusive_table(X, !MI) :-
!MI ^ mi_rare_info ^ mri_exclusive_table := X.
module_info_set_has_parallel_conj(!MI) :-
X = has_parallel_conj,
!MI ^ mi_rare_info ^ mri_has_parallel_conj := X.
module_info_set_has_user_event(!MI) :-
X = has_user_event,
!MI ^ mi_rare_info ^ mri_has_user_event := X.
module_info_set_direct_arg_proc_map(X, !MI) :-
!MI ^ mi_rare_info ^ mri_direct_arg_proc_map := X.
module_info_set_foreign_decl_codes_user(X, !MI) :-
!MI ^ mi_rare_info ^ mri_foreign_decl_codes_user := X.
module_info_set_foreign_decl_codes_aux(X, !MI) :-
!MI ^ mi_rare_info ^ mri_foreign_decl_codes_aux := X.
module_info_set_foreign_body_codes(X, !MI) :-
!MI ^ mi_rare_info ^ mri_foreign_body_codes := X.
module_info_set_int_bad_clauses(X, !MI) :-
!MI ^ mi_rare_info ^ mri_int_bad_clauses := X.
module_info_set_maybe_dependency_info(X, !MI) :-
!MI ^ mi_rare_info ^ mri_maybe_dependency_info := X.
module_info_set_type_ctor_gen_infos(X, !MI) :-
!MI ^ mi_rare_info ^ mri_type_ctor_gen_infos := X.
module_info_set_must_be_stratified_preds(X, !MI) :-
!MI ^ mi_rare_info ^ mri_must_be_stratified_preds := X.
module_info_set_unused_arg_info(X, !MI) :-
!MI ^ mi_rare_info ^ mri_unused_arg_info := X.
module_info_set_table_struct_map(X, !MI) :-
!MI ^ mi_rare_info ^ mri_table_struct_map := X.
module_info_set_lambdas_per_context(X, !MI) :-
!MI ^ mi_rare_info ^ mri_lambdas_per_context := X.
module_info_set_atomics_per_context(X, !MI) :-
!MI ^ mi_rare_info ^ mri_atomics_per_context := X.
module_info_set_loop_invs_per_context(X, !MI) :-
!MI ^ mi_rare_info ^ mri_loop_invs_per_context := X.
module_info_set_used_modules(X, !MI) :-
!MI ^ mi_rare_info ^ mri_used_modules := X.
module_info_set_ancestor_avail_modules(X, !MI) :-
!MI ^ mi_rare_info ^ mri_ancestor_avail_modules := X.
module_info_set_maybe_complexity_proc_map(X, !MI) :-
!MI ^ mi_rare_info ^ mri_maybe_complexity_proc_map := X.
module_info_set_complexity_proc_infos(X, !MI) :-
!MI ^ mi_rare_info ^ mri_complexity_proc_infos := X.
module_info_set_proc_analysis_kinds(X, !MI) :-
!MI ^ mi_rare_info ^ mri_proc_analysis_kinds := X.
module_info_set_analysis_info(X, !MI) :-
!MI ^ mi_rare_info ^ mri_analysis_info := X.
module_info_set_user_init_pred_target_names(X, !MI) :-
!MI ^ mi_rare_info ^ mri_user_init_pred_target_names := X.
module_info_set_user_final_pred_target_names(X, !MI) :-
!MI ^ mi_rare_info ^ mri_user_final_pred_target_names := X.
module_info_set_structure_reuse_preds(X, !MI) :-
!MI ^ mi_rare_info ^ mri_structure_reuse_preds := X.
module_info_set_format_call_pragma_preds(X, !MI) :-
!MI ^ mi_rare_info ^ mri_format_call_pragma_preds := X.
module_info_set_exported_enums(X, !MI) :-
!MI ^ mi_rare_info ^ mri_exported_enums := X.
module_info_set_event_set(X, !MI) :-
!MI ^ mi_rare_info ^ mri_event_set := X.
module_info_set_oisu_map(X, !MI) :-
!MI ^ mi_rare_info ^ mri_oisu_map := X.
module_info_set_oisu_procs(X, !MI) :-
!MI ^ mi_rare_info ^ mri_oisu_procs := X.
module_info_set_ts_rev_string_table(X, Y, !MI) :-
!MI ^ mi_rare_info ^ mri_ts_string_table_size := X,
!MI ^ mi_rare_info ^ mri_ts_rev_string_table := Y.
module_info_set_type_repn_dec(X, !MI) :-
!MI ^ mi_rare_info ^ mri_type_repn_dec := X.
%---------------------------------------------------------------------------%
%
% Utility predicates that are a bit more complicated than
% a simple getter or setter predicates.
%
module_info_get_pred_id_table(MI, PredIdTable) :-
module_info_get_predicate_table(MI, PredTable),
predicate_table_get_pred_id_table(PredTable, PredIdTable).
module_info_set_pred_id_table(PredIdTable, !MI) :-
module_info_get_predicate_table(!.MI, PredTable0),
predicate_table_set_pred_id_table(PredIdTable, PredTable0, PredTable),
module_info_set_predicate_table(PredTable, !MI).
module_info_pred_info(MI, PredId, PredInfo) :-
module_info_get_pred_id_table(MI, PredIdTable),
( if map.search(PredIdTable, PredId, PredInfoPrime) then
PredInfo = PredInfoPrime
else
pred_id_to_int(PredId, PredInt),
string.int_to_string(PredInt, PredStr),
unexpected($pred, "cannot find predicate number " ++ PredStr)
).
module_info_proc_info(MI, PPId, ProcInfo) :-
module_info_pred_proc_info(MI, PPId, _, ProcInfo).
module_info_proc_info(MI, PredId, ProcId, ProcInfo) :-
module_info_pred_proc_info(MI, PredId, ProcId, _, ProcInfo).
module_info_pred_proc_info(MI, PredId, ProcId, PredInfo, ProcInfo) :-
module_info_pred_info(MI, PredId, PredInfo),
pred_info_get_proc_table(PredInfo, Procs),
map.lookup(Procs, ProcId, ProcInfo).
module_info_pred_proc_info(MI, proc(PredId, ProcId), PredInfo, ProcInfo) :-
module_info_pred_proc_info(MI, PredId, ProcId, PredInfo, ProcInfo).
module_info_get_valid_pred_id_set(MI, PredIdSet) :-
module_info_get_predicate_table(MI, PredTable),
predicate_table_get_valid_pred_id_set(PredTable, PredIdSet).
module_info_get_valid_pred_ids(MI, PredIds) :-
module_info_get_predicate_table(MI, PredTable),
predicate_table_get_valid_pred_id_set(PredTable, PredIdSet),
set_tree234.to_sorted_list(PredIdSet, PredIds).
module_info_make_pred_id_invalid(PredId, !MI) :-
module_info_get_predicate_table(!.MI, PredTable0),
predicate_table_make_pred_id_invalid(PredId, PredTable0, PredTable),
module_info_set_predicate_table(PredTable, !MI).
module_info_make_pred_ids_invalid(PredIds, !MI) :-
module_info_get_predicate_table(!.MI, PredTable0),
predicate_table_make_pred_ids_invalid(PredIds, PredTable0, PredTable),
module_info_set_predicate_table(PredTable, !MI).
module_info_remove_predicate(PredId, !MI) :-
module_info_get_predicate_table(!.MI, PredTable0),
predicate_table_remove_predicate(PredId, PredTable0, PredTable),
module_info_set_predicate_table(PredTable, !MI).
module_info_set_pred_info(PredId, PredInfo, !MI) :-
module_info_get_pred_id_table(!.MI, PredIdTable0),
% XXX Should be map.det_update.
map.set(PredId, PredInfo, PredIdTable0, PredIdTable),
module_info_set_pred_id_table(PredIdTable, !MI).
module_info_set_pred_proc_info(proc(PredId, ProcId), PredInfo, ProcInfo,
!MI) :-
module_info_set_pred_proc_info(PredId, ProcId,
PredInfo, ProcInfo, !MI).
module_info_set_pred_proc_info(PredId, ProcId, PredInfo0, ProcInfo, !MI) :-
% XXX Should be pred_info_set_proc_info, which calls map.det_update.
pred_info_get_proc_table(PredInfo0, Procs0),
map.set(ProcId, ProcInfo, Procs0, Procs),
pred_info_set_proc_table(Procs, PredInfo0, PredInfo),
module_info_set_pred_info(PredId, PredInfo, !MI).
%---------------------%
predicate_id(ModuleInfo, PredId, ModuleName, PredName, Arity) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
ModuleName = pred_info_module(PredInfo),
PredName = pred_info_name(PredInfo),
Arity = pred_info_orig_arity(PredInfo).
predicate_module(ModuleInfo, PredId) = ModuleName :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
ModuleName = pred_info_module(PredInfo).
predicate_name(ModuleInfo, PredId) = PredName :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
PredName = pred_info_name(PredInfo).
predicate_arity(ModuleInfo, PredId) = Arity :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
Arity = pred_info_orig_arity(PredInfo).
%---------------------%
module_add_foreign_decl_code_user(ForeignDeclCode, !Module) :-
module_info_get_foreign_decl_codes_user(!.Module, ForeignDeclCodes0),
ForeignDeclCodes = cord.snoc(ForeignDeclCodes0, ForeignDeclCode),
module_info_set_foreign_decl_codes_user(ForeignDeclCodes, !Module).
module_add_foreign_decl_code_aux(ForeignDeclCode, !Module) :-
module_info_get_foreign_decl_codes_aux(!.Module, ForeignDeclCodes0),
ForeignDeclCodes = cord.snoc(ForeignDeclCodes0, ForeignDeclCode),
module_info_set_foreign_decl_codes_aux(ForeignDeclCodes, !Module).
module_add_foreign_body_code(ForeignBodyCode, !Module) :-
module_info_get_foreign_body_codes(!.Module, ForeignBodyCodes0),
ForeignBodyCodes = cord.snoc(ForeignBodyCodes0, ForeignBodyCode),
module_info_set_foreign_body_codes(ForeignBodyCodes, !Module).
module_add_item_fim(ItemFIM, !Module) :-
module_info_get_c_j_cs_fims(!.Module, FIMs0),
ItemFIM = item_fim(Lang, ModuleName, _Context, _SeqNum),
add_fim(Lang, ModuleName, FIMs0, FIMs),
module_info_set_c_j_cs_fims(FIMs, !Module).
module_add_fact_table_file(FileName, !Module) :-
FileNames0 = !.Module ^ mi_rare_info ^ mri_fact_table_file_names,
FileNames = [FileName | FileNames0],
!Module ^ mi_rare_info ^ mri_fact_table_file_names := FileNames.
%---------------------%
module_info_dependency_info(MI, DepInfo) :-
module_info_get_maybe_dependency_info(MI, MaybeDepInfo),
(
MaybeDepInfo = yes(DepInfoPrime),
DepInfo = DepInfoPrime
;
MaybeDepInfo = no,
unexpected($pred, "attempted to access invalid dependency_info")
).
module_info_set_dependency_info(DependencyInfo, !MI) :-
module_info_set_maybe_dependency_info(yes(DependencyInfo), !MI).
module_info_clobber_dependency_info(!MI) :-
module_info_set_maybe_dependency_info(no, !MI).
%---------------------%
module_info_next_lambda_count(Context, Count, !MI) :-
module_info_get_lambdas_per_context(!.MI, ContextCounter0),
( if
map.insert(Context, counter.init(2),
ContextCounter0, FoundContextCounter)
then
Count = 1,
ContextCounter = FoundContextCounter
else
map.lookup(ContextCounter0, Context, Counter0),
counter.allocate(Count, Counter0, Counter),
map.det_update(Context, Counter, ContextCounter0, ContextCounter)
),
module_info_set_lambdas_per_context(ContextCounter, !MI).
module_info_next_atomic_count(Context, Count, !MI) :-
module_info_get_atomics_per_context(!.MI, ContextCounter0),
( if
map.insert(Context, counter.init(2),
ContextCounter0, FoundContextCounter)
then
Count = 1,
ContextCounter = FoundContextCounter
else
map.lookup(ContextCounter0, Context, Counter0),
counter.allocate(Count, Counter0, Counter),
map.det_update(Context, Counter, ContextCounter0, ContextCounter)
),
module_info_set_atomics_per_context(ContextCounter, !MI).
module_info_next_loop_inv_count(Context, Count, !MI) :-
module_info_get_loop_invs_per_context(!.MI, ContextCounter0),
( if
map.insert(Context, counter.init(2),
ContextCounter0, FoundContextCounter)
then
Count = 1,
ContextCounter = FoundContextCounter
else
map.lookup(ContextCounter0, Context, Counter0),
counter.allocate(Count, Counter0, Counter),
map.det_update(Context, Counter, ContextCounter0, ContextCounter)
),
module_info_set_loop_invs_per_context(ContextCounter, !MI).
%---------------------%
module_add_avail_module_name(ModuleName, NewSection, NewImportOrUse,
MaybeContext, !MI) :-
(
MaybeContext = no,
NewAvails = []
;
MaybeContext = yes(Context),
NewAvails = [avail_module(NewSection, NewImportOrUse, Context)]
),
AvailMap0 = !.MI ^ mi_rare_info ^ mri_avail_module_map,
( if map.search(AvailMap0, ModuleName, OldEntry) then
OldEntry = avail_module_entry(OldSection, OldImportOrUse, OldAvails),
% XXX: If one of the entries (new or old) is a use_module in the
% interface section, while the other is an import_module in the
% implementation section, the result *ought* to be something like
% the int_use_imp_import alternative of the section_import_or_use type,
% BUT the design of avail_module_entry has no way to express that.
% The code of combine_old_new_avail_attrs returns "import_module in the
% interface section" in such cases, which is almost certainly a bug.
combine_old_new_avail_attrs(OldSection, NewSection,
OldImportOrUse, NewImportOrUse, Section, ImportOrUse),
Avails = NewAvails ++ OldAvails,
NewEntry = avail_module_entry(Section, ImportOrUse, Avails),
map.det_update(ModuleName, NewEntry, AvailMap0, AvailMap)
else
NewEntry = avail_module_entry(NewSection, NewImportOrUse, NewAvails),
map.det_insert(ModuleName, NewEntry, AvailMap0, AvailMap)
),
!MI ^ mi_rare_info ^ mri_avail_module_map := AvailMap.
:- pred combine_old_new_avail_attrs(module_section::in, module_section::in,
import_or_use::in, import_or_use::in,
module_section::out, import_or_use::out) is det.
combine_old_new_avail_attrs(OldSection, NewSection,
OldImportOrUse, NewImportOrUse, Section, ImportOrUse) :-
( if
( OldSection = ms_interface
; NewSection = ms_interface
)
then
Section = ms_interface
else
Section = ms_implementation
),
( if
( OldImportOrUse = import_decl
; NewImportOrUse = import_decl
)
then
ImportOrUse = import_decl
else
ImportOrUse = use_decl
).
module_add_indirectly_imported_module_name(AddedModuleSpecifier, !MI) :-
Modules0 = !.MI ^ mi_rare_info ^ mri_indirectly_imported_module_names,
set.insert(AddedModuleSpecifier, Modules0, Modules),
!MI ^ mi_rare_info ^ mri_indirectly_imported_module_names := Modules.
module_info_get_visible_modules(ModuleInfo, !:VisibleModules) :-
module_info_get_name(ModuleInfo, ThisModule),
module_info_get_avail_module_map(ModuleInfo, AvailModuleMap),
map.keys(AvailModuleMap, AvailModules),
set.list_to_set(AvailModules, !:VisibleModules),
set.insert(ThisModule, !VisibleModules),
set.insert_list(get_ancestors(ThisModule), !VisibleModules).
module_info_get_all_deps(ModuleInfo, AllImports) :-
module_info_get_name(ModuleInfo, ModuleName),
Parents = get_ancestors(ModuleName),
module_info_get_avail_module_map(ModuleInfo, AvailModuleMap),
map.keys(AvailModuleMap, DirectImports),
module_info_get_indirectly_imported_module_names(ModuleInfo,
IndirectImports),
AllImports = set.union_list([IndirectImports,
set.list_to_set(DirectImports), set.list_to_set(Parents)]).
module_info_add_module_to_public_used_modules(ModuleName, !MI) :-
module_info_get_used_modules(!.MI, UsedModules0),
record_module_and_ancestors_as_used(visibility_public, ModuleName,
UsedModules0, UsedModules),
module_info_set_used_modules(UsedModules, !MI).
%---------------------%
module_info_user_init_pred_target_names(MI, CNames) :-
module_info_get_user_init_pred_target_names(MI, InitPredTargetNames),
InitPredTargetNames = pred_target_names(SeqNumToPredTargetNamesMap),
map.values(SeqNumToPredTargetNamesMap, PredTargetNamesLists),
list.condense(PredTargetNamesLists, PredTargetNames),
CNames = assoc_list.values(PredTargetNames).
module_info_user_final_pred_target_names(MI, CNames) :-
module_info_get_user_final_pred_target_names(MI, FinalPredTargetNames),
FinalPredTargetNames = pred_target_names(SeqNumToPredTargetNamesMap),
map.values(SeqNumToPredTargetNamesMap, PredTargetNamesLists),
list.condense(PredTargetNamesLists, PredTargetNames),
CNames = assoc_list.values(PredTargetNames).
module_info_user_init_pred_procs(MI, PredProcIds) :-
module_info_get_user_init_pred_target_names(MI, InitPredTargetNames),
InitPredTargetNames = pred_target_names(SeqNumToPredTargetNamesMap),
map.values(SeqNumToPredTargetNamesMap, PredTargetNamesLists),
list.condense(PredTargetNamesLists, PredTargetNames),
SymNamesArities = assoc_list.keys(PredTargetNames),
list.map(get_unique_pred_proc_id_for_pred_sym_name_arity(MI),
SymNamesArities, PredProcIds).
module_info_user_final_pred_procs(MI, PredProcIds) :-
module_info_get_user_final_pred_target_names(MI, FinalPredTargetNames),
FinalPredTargetNames = pred_target_names(SeqNumToPredTargetNamesMap),
map.values(SeqNumToPredTargetNamesMap, PredTargetNamesLists),
list.condense(PredTargetNamesLists, PredTargetNames),
SymNamesArities = assoc_list.keys(PredTargetNames),
list.map(get_unique_pred_proc_id_for_pred_sym_name_arity(MI),
SymNamesArities, PredProcIds).
:- pred get_unique_pred_proc_id_for_pred_sym_name_arity(module_info::in,
sym_name_arity::in, pred_proc_id::out) is det.
get_unique_pred_proc_id_for_pred_sym_name_arity(MI, SNA, PredProcId) :-
module_info_get_predicate_table(MI, PredTable),
SNA = sym_name_arity(SymName, Arity),
UserArity = user_arity(Arity),
predicate_table_lookup_pred_sym_arity(PredTable,
may_be_partially_qualified, SymName, UserArity, PredIds),
( if PredIds = [PredId] then
pred_table.get_single_proc_id(MI, PredId, ProcId),
PredProcId = proc(PredId, ProcId)
else
unexpected($pred, "lookup failed")
).
%---------------------------------------------------------------------------%
:- end_module hlds.hlds_module.
%---------------------------------------------------------------------------%