mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
The objective of this step is two-fold:
- to fix --inhibit-warnings, making it shut up all warning
and informational messages; and
- to ensure that it *stays* fixed, even when after new diagnostics
are added.
As part of this fix, this diff adds a whole bunch of new warning
options, in order to control the warnings that previously were
not controlled by any option. (There was no need for new
informational options.)
As it happens, we have long used severity_informational for messages
that did not report any information about the code being compiled,
but to report actions that the compiler was taking. Create a new
option category, oc_report, for the new options that now control
those diagnostics.
---------------------
compiler/error_spec.m:
Change severity_warning and severity_informational to take an option
as as argument. The semantics is that the diagnostic in which
the severity occurs is conditional on that option, meaning that
it is printed only if that option is set to "yes".
Delete the severity_conditional function symbol from the severity
type, since the mechanism just above handles its only use case.
Define subtypes to represent error_specs in a standard form.
compiler/error_sort.m:
Provide operations to convert error specs into their standard form.
Make the sorting operation itself operate on the standard form.
compiler/write_error_spec.m:
Convert error_specs to standard form before writing them out,
in order to avoid duplicating the code for their standardization.
Change the code that writes out error_specs to operate on the
standard form. Implement the test implicit in the warning and
and informational severities in this code.
compiler/error_util.m:
compiler/compiler_util.m:
Delete operations that do not make sense with the new severity type.
---------------------
compiler/options.m:
Add new options to control all the previously-uncontrolled
warning and informational messages.
NEWS.md:
Announce the *public* new options.
compiler/option_categories.m:
compiler/print_help.m:
Add the new option category, and fake-include it in the help text
and the user guide. (The inclusion is fake because none of the
options in the new category are user visible, meaning the section
containing them is not visible either.)
---------------------
compiler/det_infer_goal.m:
Start a severity warning diagnostic with "Warning:"
instead of "Error:".
compiler/mark_trace_goals.m:
Fix an incorrect error message.
compiler/purity.m:
Replace a correct/incorrect color pair with two inconsistent colors,
because there is a reasonable probability of each one being right.
---------------------
compiler/accumulator.m:
compiler/add_clause.m:
compiler/add_mode.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/check_module_interface.m:
compiler/check_type_inst_mode_defns.m:
compiler/check_typeclass.m:
compiler/color_schemes.m:
compiler/common.m:
compiler/convert_import_use.m:
compiler/convert_parse_tree.m:
compiler/dead_proc_elim.m:
compiler/det_check_proc.m:
compiler/det_check_switch.m:
compiler/det_infer_goal.m:
compiler/du_type_layout.m:
compiler/format_call_errors.m:
compiler/grab_modules.m:
compiler/hlds_call_tree.m:
compiler/inst_check.m:
compiler/introduce_parallelism.m:
compiler/make_hlds_error.m:
compiler/make_hlds_warn.m:
compiler/mark_tail_calls.m:
compiler/mark_trace_goals.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_make_hlds.m:
compiler/mode_errors.m:
compiler/modes.m:
compiler/module_qual.qual_errors.m:
compiler/opt_deps_spec.m:
compiler/options_file.m:
compiler/parse_goal.m:
compiler/post_term_analysis.m:
compiler/post_typecheck.m:
compiler/pre_typecheck.m:
compiler/purity.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/simplify_goal.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/split_parse_tree_src.m:
compiler/state_var.m:
compiler/stratify.m:
compiler/style_checks.m:
compiler/superhomogeneous.m:
compiler/table_gen.m:
compiler/term_constr_errors.m:
compiler/term_errors.m:
compiler/termination.m:
compiler/typecheck_clauses.m:
compiler/typecheck_error_overload.m:
compiler/typecheck_error_undef.m:
compiler/typecheck_errors.m:
compiler/typecheck_msgs.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/warn_unread_modules.m:
compiler/write_module_interface_files.m:
Conform to the changes above, mostly by either
- adding an option to all warning and informational messages,
sometimes using existing warning options and sometimes new ones,
or
- turning already explicitly-conditional-on-an-option messages
into implicitly-conditional-on-that-option messages.
---------------------
tests/invalid/one_member.m:
Conform to the change in det_infer_goal.m.
tests/invalid/require_tailrec_1.err_exp:
tests/invalid/require_tailrec_2.err_exp:
Actually obey the options for these modules in Mercury.options.
tests/invalid_purity/purity.err_exp:
tests/warnings/purity_warnings.err_exp:
Conform to the change in purity.m.
tests/warnings/moved_trace_goal.err_exp:
Conform to the change in mark_trace_goals.m.
tests/warnings/help_text.err_exp:
Expect the documentation of all the new options.
1731 lines
78 KiB
Mathematica
1731 lines
78 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1996-2011 The University of Melbourne.
|
|
% Copyright (C) 2019-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: grab_modules.m.
|
|
% Main author: fjh (original), zs (current).
|
|
%
|
|
% When the compiler is processing a module, it uses the code in this module
|
|
% to grab files that earlier compiler invocations have automatically generated
|
|
% for some of the *other* modules of the program.
|
|
%
|
|
% This module does this in four circumstances, each of which requires it
|
|
% to grab a different set of files from a different set of modules.
|
|
%
|
|
% 1 grab_unqual_imported_modules_make_int performs the task that is
|
|
% chronologically first in the build-system lifecycle of a module,
|
|
% named (say) module A. This task is to grab all the .int3 files needed
|
|
% for the creation of A.int0, A.int, and A.int2. This task returns
|
|
% its results as an aug_make_int_unit structure.
|
|
%
|
|
% 2 grab_qual_imported_modules_augment performs the next task
|
|
% chronologically, which is to grab all the .int0, .int and .int2 files
|
|
% needed for the creation of A.c, A.cs, A.java, A.opt, A.trans_opt,
|
|
% and for all the other tasks described by op_mode_augment.
|
|
% (Hence the suffix on the name.) This task returns its results
|
|
% as an aug_compilation_unit structure.
|
|
%
|
|
% 3 grab_plain_opt_and_int_for_opt_files performs the third task
|
|
% chronologically, which is to grab all the .opt files needed
|
|
% for applying intermodule optimization to module A, together
|
|
% with any .int0 and/or .int files needed to make sense of their
|
|
% contents. This task records its results by updating an existing
|
|
% aug_compilation_unit structure.
|
|
%
|
|
% 4 grab_trans_opt_files performs the fourth task chronologically,
|
|
% which is to grab all the .trans_opt files needed for applying
|
|
% *transitive* intermodule optimization to module A. It also records
|
|
% its results by updating an existing aug_compilation_unit structure.
|
|
%
|
|
% The roles of the interface files (.int0, .int3, .int2 and .int) that
|
|
% this module reads in are documented (to the extent that they are documented
|
|
% anywhere) in the modules that create them, which are comp_unit_interface.m
|
|
% and (to a limited extent) write_module_interface_files.m.
|
|
%
|
|
% XXX The file notes/interface_files.html contains (a start on) some
|
|
% more comprehensive documentation.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.grab_modules.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.timestamp.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.module_baggage.
|
|
:- import_module parse_tree.prog_parse_tree.
|
|
:- import_module parse_tree.read_modules.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% grab_unqual_imported_modules_make_int(ProgressStream, Globals,
|
|
% ParseTreeModuleSrc, AugMakeIntUnit, !Baggage, !HaveParseTreeMaps, !IO):
|
|
%
|
|
% Given ParseTreeModuleSrc, one of the modules stored in SourceFileName,
|
|
% read in all the interface files needed to generate its .int0, .int and
|
|
% .int2 files. (We can generate .int3 files without reading anything.)
|
|
%
|
|
% Specifically, this predicate will read in
|
|
%
|
|
% - the private interface files (.int0) files for all ancestor modules,
|
|
% and
|
|
% - the unqualified short interface files (.int3) for all the directly
|
|
% and indirectly imported modules.
|
|
%
|
|
% Return the aug_make_int_unit structure containing all the information
|
|
% gathered this way.
|
|
%
|
|
% !HaveParseTreeMaps records the parse trees we have gained access to.
|
|
%
|
|
:- pred grab_unqual_imported_modules_make_int(io.text_output_stream::in,
|
|
globals::in, parse_tree_module_src::in, aug_make_int_unit::out,
|
|
module_baggage::in, module_baggage::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
io::di, io::uo) is det.
|
|
|
|
% grab_qual_imported_modules_augment(ProgressStream, Globals,
|
|
% MaybeTimestamp, ParseTreeModuleSrc, !AugCompUnit, !Baggage,
|
|
% !HaveParseTreeMaps, !IO):
|
|
%
|
|
% Given ParseTreeModuleSrc, one of the modules stored in SourceFileName,
|
|
% read in all the interface files needed to generate target language
|
|
% code for that module, or to perform a related task that requires
|
|
% the same information, such as creating .opt or .trans_opt files.
|
|
% These tasks are all op_mode_augment tasks.
|
|
%
|
|
% Specifically, this predicate will read in
|
|
%
|
|
% - the private interface files (.int0) for all ancestor modules,
|
|
% - the long interface files (.int) for all the imported modules, and
|
|
% - the qualified short interface files (.int2) for all the indirectly
|
|
% imported modules.
|
|
%
|
|
% Return the aug_compilation_unit structure containing all the information
|
|
% gathered this way.
|
|
%
|
|
% SourceFileModuleName is the top-level module name in SourceFileName.
|
|
% ModuleTimestamp is the timestamp of the SourceFileName.
|
|
% !HaveParseTreeMaps records the parse trees we have gained access to.
|
|
%
|
|
:- pred grab_qual_imported_modules_augment(io.text_output_stream::in,
|
|
globals::in, maybe(timestamp)::in, parse_tree_module_src::in,
|
|
aug_compilation_unit::out, module_baggage::in, module_baggage::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
io::di, io::uo) is det.
|
|
|
|
:- type maybe_opt_file_error
|
|
---> no_opt_file_error
|
|
; opt_file_error.
|
|
|
|
% grab_plain_opt_and_int_for_opt_files(ProgressStream, Globals, FoundError,
|
|
% !Baggage, !AugCompUnit, !HaveParseTreeMaps, !IO):
|
|
%
|
|
% Add the contents of the .opt files of imported modules, as well as
|
|
% the .int files needed to make sense of them, to !AugCompUnit.
|
|
%
|
|
:- pred grab_plain_opt_and_int_for_opt_files(io.text_output_stream::in,
|
|
io.text_output_stream::in, globals::in, maybe_opt_file_error::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
io::di, io::uo) is det.
|
|
|
|
% grab_trans_opt_files(ProgressStream, Globals, Modules, FoundError,
|
|
% !Baggage, !AugCompUnit, !HaveParseTreeMaps, !IO):
|
|
%
|
|
% Add the contents of the .trans_opt file of each module in Modules
|
|
% to !AugCompUnit.
|
|
%
|
|
:- pred grab_trans_opt_files(io.text_output_stream::in, globals::in,
|
|
list(module_name)::in, maybe_opt_file_error::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.file_util.
|
|
:- import_module libs.optimization_options.
|
|
:- import_module libs.options.
|
|
:- import_module mdbcomp.builtin_modules.
|
|
:- import_module parse_tree.check_import_accessibility.
|
|
:- import_module parse_tree.convert_import_use.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.file_kind.
|
|
:- import_module parse_tree.file_names.
|
|
:- import_module parse_tree.get_dependencies.
|
|
:- import_module parse_tree.item_util.
|
|
:- import_module parse_tree.parse_error.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_data_foreign.
|
|
:- import_module parse_tree.prog_item.
|
|
:- import_module parse_tree.write_error_spec.
|
|
|
|
:- import_module bool.
|
|
:- import_module cord.
|
|
:- import_module map.
|
|
:- import_module one_or_more.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module string.
|
|
:- import_module term_context.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
grab_unqual_imported_modules_make_int(ProgressStream, Globals,
|
|
ParseTreeModuleSrc0, !:AugMakeIntUnit,
|
|
!Baggage, !HaveParseTreeMaps, !IO) :-
|
|
% The predicates grab_imported_modules_augment and
|
|
% grab_unqual_imported_modules_make_int have quite similar tasks.
|
|
% Please keep the corresponding parts of these two predicates in sync.
|
|
%
|
|
% XXX ITEM_LIST Why aren't we updating !HaveParseTreeMaps?
|
|
|
|
some [!IntIndirectImported, !ImpIndirectImported]
|
|
(
|
|
GrabbedFileMap0 = !.Baggage ^ mb_grabbed_file_map,
|
|
map.set(ModuleName, gf_src(ParseTreeModuleSrc0),
|
|
GrabbedFileMap0, GrabbedFileMap1),
|
|
!Baggage ^ mb_grabbed_file_map := GrabbedFileMap1,
|
|
% XXX For most of Mercury's existence, we have not looked for
|
|
% or reported any errors when creating interface files. This means
|
|
% that some parts of the compiler cannot properly handle any errors
|
|
% being reported at such times. We have been changing this slowly
|
|
% since 2015, starting with the replacement of item lists with
|
|
% proper structured ASTs as the representations of interface files.
|
|
% However, the process has not finished yet. This next line shouldn't
|
|
% be there, since it prevents us from reporting some errors during
|
|
% the creation of .int/.int2/.int0 files, but without it, we get
|
|
% about 25 more test case failures during a C# bootcheck
|
|
% (going from 170 test failures to 195 on 2023 oct 22).
|
|
!Baggage ^ mb_errors := init_read_module_errors,
|
|
|
|
ModuleName = ParseTreeModuleSrc0 ^ ptms_module_name,
|
|
SrcMap0 = !.HaveParseTreeMaps ^ hptm_module_src,
|
|
map.set(ModuleName, ParseTreeModuleSrc0, SrcMap0, SrcMap),
|
|
!HaveParseTreeMaps ^ hptm_module_src := SrcMap,
|
|
|
|
init_aug_make_int_unit(ParseTreeModuleSrc0, !:AugMakeIntUnit),
|
|
|
|
ImportAndOrUseMap0 = ParseTreeModuleSrc0 ^ ptms_import_use_map,
|
|
import_and_or_use_map_to_module_name_contexts(ImportAndOrUseMap0,
|
|
IntImportMap0, IntUseMap0, ImpImportMap0, ImpUseMap0,
|
|
IntUseImpImportMap0),
|
|
map.keys_as_set(IntImportMap0, IntImports0),
|
|
map.keys_as_set(IntUseMap0, IntUses),
|
|
map.keys_as_set(ImpImportMap0, ImpImports),
|
|
map.keys_as_set(ImpUseMap0, ImpUses),
|
|
map.keys_as_set(IntUseImpImportMap0, IntUsesImpImports),
|
|
set.insert(mercury_public_builtin_module, IntImports0, IntImports),
|
|
|
|
% Get the .int0 files of the ancestor modules.
|
|
Ancestors = get_ancestors(ModuleName),
|
|
grab_module_int0_files_for_amiu(ProgressStream, Globals,
|
|
"unqual_ancestors",
|
|
Ancestors, set.init, AncestorImports, set.init, AncestorUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO),
|
|
|
|
% Get the .int3 files of the modules imported using `import_module'.
|
|
set.init(!:IntIndirectImported),
|
|
set.init(!:ImpIndirectImported),
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_parent_imported", rwi3_direct_ancestor_import,
|
|
set.to_sorted_list(AncestorImports),
|
|
!IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_int_imported", rwi3_direct_int_import,
|
|
set.to_sorted_list(IntImports),
|
|
!IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_imp_imported", rwi3_direct_imp_import,
|
|
set.to_sorted_list(ImpImports),
|
|
!ImpIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
|
|
% Get the .int3 files of the modules imported using `use_module'.
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_parent_used", rwi3_direct_ancestor_use,
|
|
set.to_sorted_list(AncestorUses),
|
|
!IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_int_used", rwi3_direct_int_use,
|
|
set.to_sorted_list(IntUses),
|
|
!IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_imp_used", rwi3_direct_imp_use,
|
|
set.to_sorted_list(ImpUses),
|
|
!ImpIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
|
|
% Get the .int3 files of the modules imported using `use_module'
|
|
% in the interface and `import_module' in the implementation.
|
|
grab_module_int3_files(ProgressStream, Globals,
|
|
"unqual_int_used_imp_imported", rwi3_direct_int_use_imp_import,
|
|
set.to_sorted_list(IntUsesImpImports),
|
|
!IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
|
|
% Get the .int3 files of the modules imported in .int3 files.
|
|
grab_module_int3_files_transitively(ProgressStream, Globals,
|
|
"unqual_int_indirect_imported", rwi3_indirect_int_use,
|
|
!.IntIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
grab_module_int3_files_transitively(ProgressStream, Globals,
|
|
"unqual_imp_indirect_imported", rwi3_indirect_imp_use,
|
|
!.ImpIndirectImported, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO),
|
|
|
|
aug_make_int_unit_get_import_accessibility_info(!.AugMakeIntUnit,
|
|
ImportAccessibilityInfo),
|
|
check_import_accessibility(ParseTreeModuleSrc0,
|
|
ImportAccessibilityInfo, MissingModulesInt, MissingModulesImp,
|
|
DelayedSpecs, AccessSpecs),
|
|
module_baggage_add_nonfatal_specs(AccessSpecs, !Baggage),
|
|
|
|
% We handle DelayedSpecs separately from AccessSpecs because
|
|
% it is possible that
|
|
%
|
|
% - the programmer's main focus is working on some module
|
|
% *other than* ModuleName,
|
|
%
|
|
% - he/she modified ModuleName just to export something that the
|
|
% the module working on needs, and added imports for what they
|
|
% thought was the bare minimum set of modules to get that
|
|
% working, but accidentally left out some of their ancestors.
|
|
%
|
|
% In such cases, preventing the creation of ModuleName's .int file
|
|
% will force the programmer to deal with what they would view as a
|
|
% side issue *before* they can get back to what they want to
|
|
% actually work on. It is better to generate (an approximation to)
|
|
% what the .int file for ModuleName would be *after* the programmer
|
|
% has finished working on the other module, once they have
|
|
% got around to compiling ModuleName, getting AccessSpecs then,
|
|
% and adds the missing ancestors, all at times of their own
|
|
% choosing.
|
|
%
|
|
% Note that there should be one delayed spec for each missing module.
|
|
list.foldl(add_missing_int_module, MissingModulesInt,
|
|
ImportAndOrUseMap0, ImportAndOrUseMap1),
|
|
list.foldl(add_missing_imp_module, MissingModulesImp,
|
|
ImportAndOrUseMap1, ImportAndOrUseMap),
|
|
ParseTreeModuleSrc = ParseTreeModuleSrc0
|
|
^ ptms_import_use_map := ImportAndOrUseMap,
|
|
!AugMakeIntUnit ^ amiu_delayed_specs := DelayedSpecs,
|
|
!AugMakeIntUnit ^ amiu_module_src := ParseTreeModuleSrc
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred add_missing_int_module(module_name::in,
|
|
import_and_or_use_map::in, import_and_or_use_map::out) is det.
|
|
|
|
add_missing_int_module(ModuleName, !ImportAndOrUseMap) :-
|
|
( if map.search(!.ImportAndOrUseMap, ModuleName, MaybeImplicit0) then
|
|
(
|
|
MaybeImplicit0 = explicit_avail(ImportAndOrUse0),
|
|
update_missing_int_module(ImportAndOrUse0, ImportAndOrUse),
|
|
MaybeImplicit = explicit_avail(ImportAndOrUse)
|
|
;
|
|
MaybeImplicit0 = implicit_avail(Implicit0, MaybeExplicit0),
|
|
(
|
|
MaybeExplicit0 = yes(ImportAndOrUse0),
|
|
update_missing_int_module(ImportAndOrUse0, ImportAndOrUse)
|
|
;
|
|
MaybeExplicit0 = no,
|
|
ImportAndOrUse = int_use(dummy_context)
|
|
),
|
|
MaybeExplicit = yes(ImportAndOrUse),
|
|
MaybeImplicit = implicit_avail(Implicit0, MaybeExplicit)
|
|
),
|
|
map.det_update(ModuleName, MaybeImplicit, !ImportAndOrUseMap)
|
|
else
|
|
ImportAndOrUse = int_use(dummy_context),
|
|
MaybeImplicit = explicit_avail(ImportAndOrUse),
|
|
map.det_insert(ModuleName, MaybeImplicit, !ImportAndOrUseMap)
|
|
).
|
|
|
|
:- pred update_missing_int_module(
|
|
section_import_and_or_use::in, section_import_and_or_use::out) is det.
|
|
|
|
update_missing_int_module(ImportAndOrUse0, ImportAndOrUse):-
|
|
(
|
|
( ImportAndOrUse0 = int_import(_)
|
|
; ImportAndOrUse0 = int_use(_)
|
|
; ImportAndOrUse0 = int_use_imp_import(_, _)
|
|
),
|
|
unexpected($pred, "module missing from int is in int")
|
|
;
|
|
ImportAndOrUse0 = imp_use(_ImpContext),
|
|
% Using _ImpContext instead dummy_context would be misleading.
|
|
% However, which context we use probably won't matter.
|
|
ImportAndOrUse = int_use(dummy_context)
|
|
;
|
|
ImportAndOrUse0 = imp_import(ImpContext),
|
|
ImportAndOrUse = int_use_imp_import(dummy_context, ImpContext)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred add_missing_imp_module(module_name::in,
|
|
import_and_or_use_map::in, import_and_or_use_map::out) is det.
|
|
|
|
add_missing_imp_module(ModuleName, !ImportAndOrUseMap) :-
|
|
( if map.search(!.ImportAndOrUseMap, ModuleName, MaybeImplicit0) then
|
|
(
|
|
MaybeImplicit0 = explicit_avail(_),
|
|
unexpected($pred, "module missing from imp is in int or imp")
|
|
;
|
|
MaybeImplicit0 = implicit_avail(Implicit0, MaybeExplicit0),
|
|
(
|
|
MaybeExplicit0 = yes(_),
|
|
unexpected($pred, "module missing from imp is in int or imp")
|
|
;
|
|
MaybeExplicit0 = no,
|
|
ImportAndOrUse = imp_use(dummy_context)
|
|
)
|
|
),
|
|
MaybeExplicit = yes(ImportAndOrUse),
|
|
MaybeImplicit = implicit_avail(Implicit0, MaybeExplicit),
|
|
map.det_update(ModuleName, MaybeImplicit, !ImportAndOrUseMap)
|
|
else
|
|
ImportAndOrUse = imp_use(dummy_context),
|
|
MaybeImplicit = explicit_avail(ImportAndOrUse),
|
|
map.det_insert(ModuleName, MaybeImplicit, !ImportAndOrUseMap)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
grab_qual_imported_modules_augment(ProgressStream, Globals, MaybeTimestamp,
|
|
ParseTreeModuleSrc0, !:AugCompUnit, !Baggage,
|
|
!HaveParseTreeMaps, !IO) :-
|
|
% The predicates grab_imported_modules_augment and
|
|
% grab_unqual_imported_modules_make_int have quite similar tasks.
|
|
% Please keep the corresponding parts of these two predicates in sync.
|
|
%
|
|
% XXX ITEM_LIST Why aren't we updating !HaveParseTreeMaps?
|
|
some [!IntIndirectImported, !ImpIndirectImported,
|
|
!IntImpIndirectImported, !ImpImpIndirectImported]
|
|
(
|
|
ModuleName = ParseTreeModuleSrc0 ^ ptms_module_name,
|
|
(
|
|
MaybeTimestamp = yes(Timestamp),
|
|
MaybeTimestampMap0 = yes(map.singleton(ModuleName,
|
|
module_timestamp(fk_src, Timestamp, recomp_avail_src)))
|
|
;
|
|
MaybeTimestamp = no,
|
|
MaybeTimestampMap0 = no
|
|
),
|
|
!Baggage ^ mb_maybe_timestamp_map := MaybeTimestampMap0,
|
|
|
|
IntFIMs0 = ParseTreeModuleSrc0 ^ ptms_int_fims,
|
|
ImpFIMs0 = ParseTreeModuleSrc0 ^ ptms_imp_fims,
|
|
set.foldl(add_implicit_fim_for_module(ModuleName),
|
|
ParseTreeModuleSrc0 ^ ptms_int_self_fim_langs, IntFIMs0, IntFIMs),
|
|
set.foldl(add_implicit_fim_for_module(ModuleName),
|
|
ParseTreeModuleSrc0 ^ ptms_imp_self_fim_langs, ImpFIMs0, ImpFIMs),
|
|
ParseTreeModuleSrc1 = ParseTreeModuleSrc0 ^ ptms_int_fims := IntFIMs,
|
|
ParseTreeModuleSrc = ParseTreeModuleSrc1 ^ ptms_imp_fims := ImpFIMs,
|
|
|
|
% The parse_tree_module_src we want to put into the grabbed file map,
|
|
% !HaveParseTreeMaps and !:AugCompUnit is the one that has had
|
|
% implicit foreign_import_modules added to it by the block of code
|
|
% just above.
|
|
|
|
GrabbedFileMap0 = !.Baggage ^ mb_grabbed_file_map,
|
|
map.set(ModuleName, gf_src(ParseTreeModuleSrc),
|
|
GrabbedFileMap0, GrabbedFileMap1),
|
|
!Baggage ^ mb_grabbed_file_map := GrabbedFileMap1,
|
|
|
|
SrcMap0 = !.HaveParseTreeMaps ^ hptm_module_src,
|
|
% XXX Should be map.det_insert.
|
|
map.set(ModuleName, ParseTreeModuleSrc, SrcMap0, SrcMap),
|
|
!HaveParseTreeMaps ^ hptm_module_src := SrcMap,
|
|
|
|
init_aug_compilation_unit(ParseTreeModuleSrc, !:AugCompUnit),
|
|
|
|
ImportUseMap = ParseTreeModuleSrc ^ ptms_import_use_map,
|
|
import_and_or_use_map_to_module_name_contexts(ImportUseMap,
|
|
IntImportMap, IntUseMap, ImpImportMap, ImpUseMap,
|
|
IntUseImpImportMap),
|
|
map.keys_as_set(IntImportMap, IntImports0),
|
|
map.keys_as_set(IntUseMap, IntUses0),
|
|
ImpImports = map.sorted_keys(ImpImportMap),
|
|
ImpUses = map.sorted_keys(ImpUseMap),
|
|
IntUseImpImports = map.sorted_keys(IntUseImpImportMap),
|
|
|
|
% Get the .int0 files of the ancestor modules.
|
|
%
|
|
% Uses of the items declared in ancestor modules do not need
|
|
% module qualifiers. Modules imported by ancestors are considered
|
|
% to be visible in the current module.
|
|
% XXX grab_unqual_imported_modules_make_int treats AncestorImported and
|
|
% AncestorUsed slightly differently from !.IntImported and !.IntUsed.
|
|
Ancestors = get_ancestors(ModuleName),
|
|
grab_module_int0_files_for_acu(ProgressStream, Globals,
|
|
"ancestors", rwi0_section,
|
|
Ancestors, IntImports0, IntImports, IntUses0, IntUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Get the .int files of the modules imported using `import_module'.
|
|
set.init(!:IntIndirectImported),
|
|
set.init(!:ImpIndirectImported),
|
|
set.init(!:IntImpIndirectImported),
|
|
set.init(!:ImpImpIndirectImported),
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"int_imported", rwi1_int_import,
|
|
set.to_sorted_list(IntImports),
|
|
!IntIndirectImported, !IntImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"imp_imported", rwi1_imp_import,
|
|
ImpImports,
|
|
!ImpIndirectImported, !ImpImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Get the .int files of the modules imported using `use_module'.
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"int_used", rwi1_int_use,
|
|
set.to_sorted_list(IntUses),
|
|
!IntIndirectImported, !IntImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"imp_used", rwi1_imp_use,
|
|
ImpUses,
|
|
!ImpIndirectImported, !ImpImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Get the .int files of the modules imported using `use_module'
|
|
% in the interface and `import_module' in the implementation.
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"int_used_imp_imported", rwi1_int_use_imp_import,
|
|
IntUseImpImports,
|
|
!IntIndirectImported, !IntImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Get the .int2 files of the modules imported in .int files.
|
|
grab_module_int2_files_transitively(ProgressStream, Globals,
|
|
"int_indirect_imported", rwi2_int_use,
|
|
!.IntIndirectImported, !IntImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
grab_module_int2_files_transitively(ProgressStream, Globals,
|
|
"imp_indirect_imported", rwi2_imp_use,
|
|
!.ImpIndirectImported, !ImpImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Get the .int2 files of the modules indirectly imported
|
|
% the implementation sections of .int/.int2 files.
|
|
grab_module_int2_files_and_impls_transitively(ProgressStream, Globals,
|
|
"int_imp_indirect_imported", rwi2_abstract,
|
|
!.IntImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
grab_module_int2_files_and_impls_transitively(ProgressStream, Globals,
|
|
"imp_imp_indirect_imported", rwi2_abstract,
|
|
!.ImpImpIndirectImported,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
globals.lookup_bool_option(Globals, experiment3, Experiment3),
|
|
(
|
|
Experiment3 = no
|
|
;
|
|
Experiment3 = yes,
|
|
% This compiler invocation can get type representation information
|
|
% for all the types it has access to in the .int and/or .int2 files
|
|
% of the modules it imported directly or indirectly, *except* for
|
|
% the types it defines itself, and the types defined by its
|
|
% ancestors (if any). For representation information for these
|
|
% types, it must read its *own* .int file, and the .int file(s)
|
|
% of its ancestors.
|
|
grab_module_int1_file(ProgressStream, Globals, rwi1_type_repn,
|
|
ModuleName, _IntUses, _ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
list.map2_foldl4(
|
|
grab_module_int1_file(ProgressStream, Globals, rwi1_type_repn),
|
|
get_ancestors(ModuleName), _IntUsesList, _ImpUsesList,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO)
|
|
),
|
|
|
|
aug_comp_unit_get_import_accessibility_info(!.AugCompUnit,
|
|
ImportAccessibilityInfo),
|
|
check_import_accessibility(ParseTreeModuleSrc, ImportAccessibilityInfo,
|
|
_MissingModulesInt, _MissingModulesImp, DelayedSpecs, AccessSpecs),
|
|
module_baggage_add_nonfatal_specs(DelayedSpecs, !Baggage),
|
|
module_baggage_add_nonfatal_specs(AccessSpecs, !Baggage)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
grab_plain_opt_and_int_for_opt_files(ProgressStream, ErrorStream, Globals,
|
|
FoundError, !Baggage, !AugCompUnit, !HaveParseTreeMaps, !IO) :-
|
|
% Read in the .opt files for imported and ancestor modules.
|
|
ParseTreeModuleSrc = !.AugCompUnit ^ acu_module_src,
|
|
ModuleName = ParseTreeModuleSrc ^ ptms_module_name,
|
|
Ancestors0 = get_ancestors_set(ModuleName),
|
|
DirectDeps0 = map.keys_as_set(ParseTreeModuleSrc ^ ptms_import_use_map),
|
|
% Some builtin modules can implicitly depend on themselves.
|
|
% For those, we don't want to read in their .opt file, since we have
|
|
% already in their .m file.
|
|
set.delete(ModuleName, DirectDeps0, DirectDeps),
|
|
OptModules = set.union(Ancestors0, DirectDeps),
|
|
globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
|
|
globals.lookup_bool_option(Globals, read_opt_files_transitively,
|
|
ReadOptFilesTransitively),
|
|
% Do not add to the queue either the modules in the initial queue,
|
|
% or the module being compiled.
|
|
set.insert(ModuleName, OptModules, DontQueueOptModules),
|
|
read_plain_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ReadOptFilesTransitively,
|
|
set.to_sorted_list(OptModules), DontQueueOptModules,
|
|
cord.empty, ParseTreePlainOptsCord0, set.init, ExplicitDeps,
|
|
cord.empty, ImplicitNeedsCord, [], OptSpecs0,
|
|
no_opt_file_error, OptError0, !IO),
|
|
ParseTreePlainOpts0 = cord.list(ParseTreePlainOptsCord0),
|
|
|
|
% Get the :- pragma unused_args(...) declarations created when writing
|
|
% the .opt file for the current module. These are needed because we can
|
|
% probably remove more arguments with intermod_unused_args, but the
|
|
% interface for other modules must remain the same.
|
|
%
|
|
% Similarly for the :- pragma structure_reuse(...) declarations. With more
|
|
% information available when making the target code than when writing the
|
|
% `.opt' file, it can turn out that a procedure which seemed to have
|
|
% condition reuse actually has none. But we have to maintain the interface
|
|
% for modules that use the conditional reuse information from the `.opt'
|
|
% file.
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
UnusedArgs = OptTuple ^ ot_opt_unused_args_intermod,
|
|
globals.lookup_bool_option(Globals, structure_reuse_analysis,
|
|
StructureReuse),
|
|
( if (UnusedArgs = opt_unused_args_intermod ; StructureReuse = yes) then
|
|
read_module_plain_opt(ProgressStream, Globals, ModuleName,
|
|
HaveReadOwnPlainOpt0, !IO),
|
|
(
|
|
HaveReadOwnPlainOpt0 = have_module(_, OwnParseTreePlainOpt0,
|
|
Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
_, OwnOptModuleErrors),
|
|
% XXX We should store the whole parse_tree, with a note next to it
|
|
% saying "keep only these two kinds of pragmas".
|
|
keep_only_unused_and_reuse_pragmas_in_parse_tree_plain_opt(
|
|
UnusedArgs, StructureReuse,
|
|
OwnParseTreePlainOpt0, OwnParseTreePlainOpt),
|
|
ParseTreePlainOpts = [OwnParseTreePlainOpt | ParseTreePlainOpts0],
|
|
update_opt_error_status_on_success(OwnOptModuleErrors,
|
|
OptSpecs0, OptSpecs1, OptError0, OptError)
|
|
;
|
|
HaveReadOwnPlainOpt0 =
|
|
have_not_read_module(OwnOptFileName, OwnOptModuleErrors),
|
|
ParseTreePlainOpts = ParseTreePlainOpts0,
|
|
update_opt_error_status_on_failure(Globals, warn_missing_opt_files,
|
|
OwnOptFileName, OwnOptModuleErrors,
|
|
OptSpecs0, OptSpecs1, OptError0, OptError)
|
|
),
|
|
maybe_write_out_errors(ErrorStream, VeryVerbose, Globals,
|
|
OptSpecs1, OptSpecs, !IO)
|
|
else
|
|
ParseTreePlainOpts = ParseTreePlainOpts0,
|
|
OptSpecs = OptSpecs0,
|
|
OptError = OptError0
|
|
),
|
|
|
|
list.foldl(aug_compilation_unit_add_plain_opt, ParseTreePlainOpts,
|
|
!AugCompUnit),
|
|
module_baggage_add_nonfatal_specs(OptSpecs, !Baggage),
|
|
|
|
% Read .int0 files required by the `.opt' files, except the ones
|
|
% we have already read as ancestors of ModuleName,
|
|
% XXX This code reads in the .int0 files of the ancestors of *OptModules*,
|
|
% but due to read_opt_files_transitively, ParseTreePlainOpts may contain
|
|
% more the .opt files of modules that are *not* in OptModules.
|
|
% This looks like a bug.
|
|
OptModuleAncestors =
|
|
set.power_union(set.map(get_ancestors_set, OptModules)),
|
|
OldModuleAncestors = get_ancestors_set(ModuleName),
|
|
set.insert(ModuleName, OldModuleAncestors, OldModuleAndAncestors),
|
|
OptOnlyModuleAncestors =
|
|
set.difference(OptModuleAncestors, OldModuleAndAncestors),
|
|
|
|
grab_module_int0_files_for_acu(ProgressStream, Globals,
|
|
"opt_int0s", rwi0_opt,
|
|
set.to_sorted_list(OptOnlyModuleAncestors),
|
|
set.init, OptAncestorImports, set.init, OptAncestorUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Figure out which .int files are implicitly needed by the .opt files.
|
|
combine_implicit_needs(cord.list(ImplicitNeedsCord), AllImplicitNeeds),
|
|
compute_implicit_avail_needs(Globals, AllImplicitNeeds, ImplicitDeps),
|
|
NewDeps = set.union_list([ExplicitDeps, ImplicitDeps,
|
|
OptAncestorImports, OptAncestorUses]),
|
|
|
|
% Read in the .int, and .int2 files needed by the .opt files.
|
|
grab_module_int1_files(ProgressStream, Globals,
|
|
"opt_new_deps", rwi1_opt,
|
|
set.to_sorted_list(NewDeps),
|
|
set.init, NewIntIndirectDeps, set.init, NewImpIndirectDeps,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
grab_module_int2_files_and_impls_transitively(ProgressStream, Globals,
|
|
"opt_new_indirect_deps", rwi2_opt,
|
|
set.union(NewIntIndirectDeps, NewImpIndirectDeps),
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
|
|
% Figure out whether anything went wrong.
|
|
% XXX We should try to put all the relevant error indications into
|
|
% !AugCompUnit, and let our caller figure out what to do with them.
|
|
ModuleErrors = !.Baggage ^ mb_errors,
|
|
( if
|
|
( set.is_non_empty(ModuleErrors ^ rm_fatal_errors)
|
|
; set.is_non_empty(ModuleErrors ^ rm_nonfatal_errors)
|
|
; OptError = opt_file_error
|
|
)
|
|
then
|
|
FoundError = opt_file_error
|
|
else
|
|
FoundError = no_opt_file_error
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
grab_trans_opt_files(ProgressStream, Globals, TransOptModuleNames, FoundError,
|
|
!Baggage, !AugCompUnit, HaveParseTreeMaps, HaveParseTreeMaps, !IO) :-
|
|
% XXX We should be using !HaveParseTreeMaps.
|
|
globals.lookup_bool_option(Globals, verbose, Verbose),
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Reading .trans_opt files..\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
|
|
globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
|
|
read_trans_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
TransOptModuleNames, cord.init, ParseTreeTransOptsCord,
|
|
[], TransOptSpecs, no_opt_file_error, FoundError, !IO),
|
|
list.foldl(aug_compilation_unit_add_trans_opt,
|
|
cord.list(ParseTreeTransOptsCord), !AugCompUnit),
|
|
module_baggage_add_nonfatal_specs(TransOptSpecs, !Baggage),
|
|
% XXX why ignore any existing errors?
|
|
!Baggage ^ mb_errors := init_read_module_errors,
|
|
|
|
maybe_write_string(ProgressStream, Verbose, "% Done.\n", !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% XXX ITEM_LIST Document what the grab_module_int* predicates do
|
|
% more precisely, and document exactly WHY they do each of their actions.
|
|
% I (zs) think it likely that some of the interface files we now read in
|
|
% are read in unnecessarily.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred grab_module_int2_files_and_impls_transitively(
|
|
io.text_output_stream::in, globals::in,
|
|
string::in, read_why_int2::in, set(module_name)::in,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int2_files_and_impls_transitively(ProgressStream, Globals,
|
|
Why, ReadWhy2, Modules, !HaveParseTreeMaps,
|
|
!Baggage, !AugCompUnit, !IO) :-
|
|
grab_module_int2_files_transitively(ProgressStream, Globals,
|
|
Why, ReadWhy2, Modules, set.init, ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
( if set.is_empty(ImpIndirectImports) then
|
|
true
|
|
else
|
|
grab_module_int2_files_and_impls_transitively(ProgressStream, Globals,
|
|
Why, ReadWhy2, ImpIndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugCompUnit, !IO)
|
|
).
|
|
|
|
:- pred grab_module_int2_files_transitively(io.text_output_stream::in,
|
|
globals::in, string::in, read_why_int2::in, set(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int2_files_transitively(ProgressStream, Globals, Why, ReadWhy2,
|
|
Modules, !ImpIndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugCompUnit, !IO) :-
|
|
grab_module_int2_files(ProgressStream, Globals, Why, ReadWhy2,
|
|
set.to_sorted_list(Modules),
|
|
set.init, IndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
( if set.is_empty(IndirectImports) then
|
|
true
|
|
else
|
|
grab_module_int2_files_transitively(ProgressStream, Globals,
|
|
Why, ReadWhy2, IndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO)
|
|
).
|
|
|
|
:- pred grab_module_int3_files_transitively(io.text_output_stream::in,
|
|
globals::in, string::in, read_why_int3::in, set(module_name)::in,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_make_int_unit::in, aug_make_int_unit::out, io::di, io::uo) is det.
|
|
|
|
grab_module_int3_files_transitively(ProgressStream, Globals, Why, ReadWhy3,
|
|
Modules, !HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO) :-
|
|
grab_module_int3_files(ProgressStream, Globals, Why, ReadWhy3,
|
|
set.to_sorted_list(Modules), set.init, IndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO),
|
|
( if set.is_empty(IndirectImports) then
|
|
true
|
|
else
|
|
grab_module_int3_files_transitively(ProgressStream, Globals,
|
|
Why, ReadWhy3, IndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO)
|
|
).
|
|
|
|
:- pred grab_module_int0_files_for_acu(io.text_output_stream::in, globals::in,
|
|
string::in, read_why_int0::in, list(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int0_files_for_acu(_ProgressStream, _Globals, _Why, _ReadWhy0, [],
|
|
!DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
grab_module_int0_files_for_acu(ProgressStream, Globals, Why, ReadWhy0,
|
|
[ModuleName | ModuleNames], !DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
( if should_read_interface(!.Baggage, ModuleName, ifk_int0) then
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int0, ReadWhy0,
|
|
ModuleName, decided_to_read, !IO),
|
|
grab_module_int0_file_for_acu(ProgressStream, Globals, ReadWhy0,
|
|
ModuleName, IntImports, ImpImports, IntUses, ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
set.union(IntImports, !DirectImports),
|
|
set.union(ImpImports, !DirectImports),
|
|
set.union(IntUses, !DirectUses),
|
|
set.union(ImpUses, !DirectUses)
|
|
else
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int0, ReadWhy0,
|
|
ModuleName, decided_not_to_read, !IO)
|
|
),
|
|
grab_module_int0_files_for_acu(ProgressStream, Globals, Why, ReadWhy0,
|
|
ModuleNames, !DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
|
|
:- pred grab_module_int0_files_for_amiu(io.text_output_stream::in, globals::in,
|
|
string::in, list(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_make_int_unit::in, aug_make_int_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int0_files_for_amiu(_ProgressStream, _Globals, _Why, [],
|
|
!DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO).
|
|
grab_module_int0_files_for_amiu(ProgressStream, Globals, Why,
|
|
[ModuleName | ModuleNames], !DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO) :-
|
|
ReadWhy0 = rwi0_section,
|
|
( if should_read_interface(!.Baggage, ModuleName, ifk_int0) then
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int0, ReadWhy0,
|
|
ModuleName, decided_to_read, !IO),
|
|
grab_module_int0_file_for_amiu(ProgressStream, Globals, ModuleName,
|
|
IntImports, ImpImports, IntUses, ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO),
|
|
set.union(IntImports, !DirectImports),
|
|
set.union(ImpImports, !DirectImports),
|
|
set.union(IntUses, !DirectUses),
|
|
set.union(ImpUses, !DirectUses)
|
|
else
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int0, ReadWhy0,
|
|
ModuleName, decided_not_to_read, !IO)
|
|
),
|
|
grab_module_int0_files_for_amiu(ProgressStream, Globals, Why, ModuleNames,
|
|
!DirectImports, !DirectUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO).
|
|
|
|
:- pred grab_module_int1_files(io.text_output_stream::in, globals::in,
|
|
string::in, read_why_int1::in, list(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int1_files(_ProgressStream, _Globals, _Why, _ReadWhy1,
|
|
[], !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
grab_module_int1_files(ProgressStream, Globals, Why, ReadWhy1,
|
|
[ModuleName | ModuleNames], !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
( if should_read_interface(!.Baggage, ModuleName, ifk_int1) then
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int1, ReadWhy1,
|
|
ModuleName, decided_to_read, !IO),
|
|
grab_module_int1_file(ProgressStream, Globals, ReadWhy1, ModuleName,
|
|
IntUses, ImpUses, !HaveParseTreeMaps,
|
|
!Baggage, !AugCompUnit, !IO),
|
|
set.union(IntUses, !IntIndirectImports),
|
|
set.union(ImpUses, !ImpIndirectImports)
|
|
else
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int1, ReadWhy1,
|
|
ModuleName, decided_not_to_read, !IO)
|
|
),
|
|
grab_module_int1_files(ProgressStream, Globals, Why, ReadWhy1,
|
|
ModuleNames, !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
|
|
:- pred grab_module_int2_files(io.text_output_stream::in, globals::in,
|
|
string::in, read_why_int2::in, list(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int2_files(_ProgressStream, _Globals, _Why, _ReadWhy2,
|
|
[], !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
grab_module_int2_files(ProgressStream, Globals, Why, ReadWhy2,
|
|
[ModuleName | ModuleNames], !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
( if should_read_interface(!.Baggage, ModuleName, ifk_int2) then
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int2, ReadWhy2,
|
|
ModuleName, decided_to_read, !IO),
|
|
grab_module_int2_file(ProgressStream, Globals, ReadWhy2, ModuleName,
|
|
IntUses, ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
|
|
set.union(IntUses, !IntIndirectImports),
|
|
set.union(ImpUses, !ImpIndirectImports)
|
|
else
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int2, ReadWhy2,
|
|
ModuleName, decided_not_to_read, !IO)
|
|
),
|
|
grab_module_int2_files(ProgressStream, Globals, Why, ReadWhy2,
|
|
ModuleNames, !IntIndirectImports, !ImpIndirectImports,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO).
|
|
|
|
:- pred grab_module_int3_files(io.text_output_stream::in, globals::in,
|
|
string::in, read_why_int3::in, list(module_name)::in,
|
|
set(module_name)::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_make_int_unit::in, aug_make_int_unit::out, io::di, io::uo) is det.
|
|
|
|
grab_module_int3_files(_ProgressStream, _Globals, _Why, _ReadWhy3,
|
|
[], !IntIndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO).
|
|
grab_module_int3_files(ProgressStream, Globals, Why, ReadWhy3,
|
|
[ModuleName | ModuleNames], !IntIndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO) :-
|
|
( if should_read_interface(!.Baggage, ModuleName, ifk_int3) then
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int3, ReadWhy3,
|
|
ModuleName, decided_to_read, !IO),
|
|
grab_module_int3_file(ProgressStream, Globals, ReadWhy3, ModuleName,
|
|
IntImports, !HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO),
|
|
set.union(IntImports, !IntIndirectImports)
|
|
else
|
|
maybe_log_augment_decision(ProgressStream, Why, ifk_int3, ReadWhy3,
|
|
ModuleName, decided_not_to_read, !IO)
|
|
),
|
|
grab_module_int3_files(ProgressStream, Globals, Why, ReadWhy3,
|
|
ModuleNames, !IntIndirectImports, !HaveParseTreeMaps,
|
|
!Baggage, !AugMakeIntUnit, !IO).
|
|
|
|
:- pred should_read_interface(module_baggage::in, module_name::in,
|
|
int_file_kind::in) is semidet.
|
|
|
|
should_read_interface(Baggage, ModuleName, FileKind) :-
|
|
GrabbedFileMap = Baggage ^ mb_grabbed_file_map,
|
|
( if map.search(GrabbedFileMap, ModuleName, OldGrabbedFile) then
|
|
OldFileKind = grabbed_file_to_file_kind(OldGrabbedFile),
|
|
( if compare((<), fk_int(FileKind), OldFileKind) then
|
|
true
|
|
else
|
|
fail
|
|
)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- func grabbed_file_to_file_kind(grabbed_file) = file_kind.
|
|
|
|
grabbed_file_to_file_kind(GrabbedWhy) = FileKind :-
|
|
( GrabbedWhy = gf_src(_), FileKind = fk_src
|
|
; GrabbedWhy = gf_int0(_, _), FileKind = fk_int(ifk_int0)
|
|
; GrabbedWhy = gf_int1(_, _), FileKind = fk_int(ifk_int1)
|
|
; GrabbedWhy = gf_int2(_, _), FileKind = fk_int(ifk_int2)
|
|
; GrabbedWhy = gf_int3(_, _), FileKind = fk_int(ifk_int3)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred grab_module_int0_file_for_acu(io.text_output_stream::in, globals::in,
|
|
read_why_int0::in, module_name::in,
|
|
set(module_name)::out, set(module_name)::out,
|
|
set(module_name)::out, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int0_file_for_acu(ProgressStream, Globals, ReadWhy0, ModuleName,
|
|
IntImports, ImpImports, IntUses, ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
do_we_need_timestamps(!.Baggage, ReturnTimestamp),
|
|
maybe_read_module_int0(ProgressStream, Globals, do_search, ModuleName,
|
|
ReturnTimestamp, HaveReadInt0, !HaveParseTreeMaps, !IO),
|
|
(
|
|
HaveReadInt0 = have_module(_FileName, ParseTreeInt0, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
MaybeTimestamp, Errors),
|
|
GrabbedFile = gf_int0(ParseTreeInt0, ReadWhy0),
|
|
module_baggage_add_grabbed_file(ModuleName, GrabbedFile, !Baggage),
|
|
(
|
|
ReadWhy0 = rwi0_section,
|
|
AncestorIntSpec = ancestor_int0(ParseTreeInt0, ReadWhy0),
|
|
aug_compilation_unit_add_ancestor_int_spec(AncestorIntSpec,
|
|
!AugCompUnit)
|
|
;
|
|
ReadWhy0 = rwi0_opt,
|
|
IntForOptSpec = for_opt_int0(ParseTreeInt0, ReadWhy0),
|
|
aug_compilation_unit_add_int_for_opt_spec(IntForOptSpec,
|
|
!AugCompUnit)
|
|
),
|
|
maybe_record_interface_timestamp(ModuleName, ifk_int0,
|
|
recomp_avail_int_import, MaybeTimestamp, !Baggage),
|
|
map.foldl4(get_imports_uses, ParseTreeInt0 ^ pti0_import_use_map,
|
|
set.init, IntImports, set.init, ImpImports,
|
|
set.init, IntUses, set.init, ImpUses),
|
|
aug_compilation_unit_maybe_add_module_version_numbers(ModuleName,
|
|
ParseTreeInt0 ^ pti0_maybe_version_numbers, !AugCompUnit)
|
|
;
|
|
HaveReadInt0 = have_not_read_module(_FileName, Errors),
|
|
set.init(IntImports),
|
|
set.init(ImpImports),
|
|
set.init(IntUses),
|
|
set.init(ImpUses)
|
|
),
|
|
module_baggage_add_errors(Errors, !Baggage).
|
|
|
|
:- pred grab_module_int0_file_for_amiu(io.text_output_stream::in,
|
|
globals::in, module_name::in,
|
|
set(module_name)::out, set(module_name)::out,
|
|
set(module_name)::out, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_make_int_unit::in, aug_make_int_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int0_file_for_amiu(ProgressStream, Globals, ModuleName,
|
|
IntImports, ImpImports, IntUses, ImpUses,
|
|
!HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO) :-
|
|
do_we_need_timestamps(!.Baggage, ReturnTimestamp),
|
|
maybe_read_module_int0(ProgressStream, Globals, do_search, ModuleName,
|
|
ReturnTimestamp, HaveReadInt0, !HaveParseTreeMaps, !IO),
|
|
(
|
|
HaveReadInt0 = have_module(_FileName, ParseTreeInt0, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
MaybeTimestamp, Errors),
|
|
GrabbedFile = gf_int0(ParseTreeInt0, rwi0_section),
|
|
module_baggage_add_grabbed_file(ModuleName, GrabbedFile, !Baggage),
|
|
aug_make_int_unit_add_ancestor_int(ParseTreeInt0, !AugMakeIntUnit),
|
|
maybe_record_interface_timestamp(ModuleName, ifk_int0,
|
|
recomp_avail_int_import, MaybeTimestamp, !Baggage),
|
|
map.foldl4(get_imports_uses, ParseTreeInt0 ^ pti0_import_use_map,
|
|
set.init, IntImports, set.init, ImpImports,
|
|
set.init, IntUses, set.init, ImpUses),
|
|
aug_make_int_unit_maybe_add_module_version_numbers(ModuleName,
|
|
ParseTreeInt0 ^ pti0_maybe_version_numbers, !AugMakeIntUnit)
|
|
;
|
|
HaveReadInt0 = have_not_read_module(_FileName, Errors),
|
|
set.init(IntImports),
|
|
set.init(ImpImports),
|
|
set.init(IntUses),
|
|
set.init(ImpUses)
|
|
),
|
|
module_baggage_add_errors(Errors, !Baggage).
|
|
|
|
:- pred grab_module_int1_file(io.text_output_stream::in, globals::in,
|
|
read_why_int1::in, module_name::in,
|
|
set(module_name)::out, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int1_file(ProgressStream, Globals, ReadWhy1, ModuleName,
|
|
IntUses, ImpUses, !HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
do_we_need_timestamps(!.Baggage, ReturnTimestamp),
|
|
maybe_read_module_int1(ProgressStream, Globals, do_search, ModuleName,
|
|
ReturnTimestamp, HaveReadInt1, !HaveParseTreeMaps, !IO),
|
|
(
|
|
HaveReadInt1 = have_module(_FileName, ParseTreeInt1, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
MaybeTimestamp, Errors),
|
|
GrabbedFile = gf_int1(ParseTreeInt1, ReadWhy1),
|
|
module_baggage_add_grabbed_file(ModuleName, GrabbedFile, !Baggage),
|
|
(
|
|
(
|
|
ReadWhy1 = rwi1_int_import,
|
|
RecompAvail = recomp_avail_int_import
|
|
;
|
|
ReadWhy1 = rwi1_int_use,
|
|
RecompAvail = recomp_avail_int_use
|
|
;
|
|
ReadWhy1 = rwi1_imp_import,
|
|
RecompAvail = recomp_avail_imp_import
|
|
;
|
|
ReadWhy1 = rwi1_imp_use,
|
|
RecompAvail = recomp_avail_imp_use
|
|
;
|
|
ReadWhy1 = rwi1_int_use_imp_import,
|
|
RecompAvail = recomp_avail_int_use_imp_import
|
|
),
|
|
DirectIntSpec = direct_int1(ParseTreeInt1, ReadWhy1),
|
|
aug_compilation_unit_add_direct_int1_spec(DirectIntSpec,
|
|
!AugCompUnit),
|
|
module_baggage_add_errors(Errors, !Baggage)
|
|
;
|
|
ReadWhy1 = rwi1_opt,
|
|
RecompAvail = recomp_avail_imp_use,
|
|
IntForOptSpec = for_opt_int1(ParseTreeInt1, ReadWhy1),
|
|
aug_compilation_unit_add_int_for_opt_spec(IntForOptSpec,
|
|
!AugCompUnit),
|
|
module_baggage_add_errors(Errors, !Baggage)
|
|
;
|
|
ReadWhy1 = rwi1_type_repn,
|
|
RecompAvail = recomp_avail_int_import,
|
|
TypeRepnSpec = type_repn_spec_int1(ParseTreeInt1),
|
|
aug_compilation_unit_add_type_repn_spec(TypeRepnSpec, !AugCompUnit)
|
|
% Do not add Errors to !AugCompUnit. Any error messages in there
|
|
% will be reported when the source file of the affected module
|
|
% is compiled to target code.
|
|
),
|
|
map.foldl2(get_uses, ParseTreeInt1 ^ pti1_use_map,
|
|
set.init, IntUses, set.init, ImpUses),
|
|
maybe_record_interface_timestamp(ModuleName, ifk_int1, RecompAvail,
|
|
MaybeTimestamp, !Baggage),
|
|
aug_compilation_unit_maybe_add_module_version_numbers(ModuleName,
|
|
ParseTreeInt1 ^ pti1_maybe_version_numbers, !AugCompUnit)
|
|
;
|
|
HaveReadInt1 = have_not_read_module(_FileName, Errors),
|
|
set.init(IntUses),
|
|
set.init(ImpUses),
|
|
module_baggage_add_errors(Errors, !Baggage)
|
|
).
|
|
|
|
:- pred grab_module_int2_file(io.text_output_stream::in, globals::in,
|
|
read_why_int2::in, module_name::in,
|
|
set(module_name)::out, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
io::di, io::uo) is det.
|
|
|
|
grab_module_int2_file(ProgressStream, Globals, ReadWhy2, ModuleName,
|
|
IntUses, ImpUses, !HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO) :-
|
|
do_we_need_timestamps(!.Baggage, ReturnTimestamp),
|
|
maybe_read_module_int2(ProgressStream, Globals, do_search, ModuleName,
|
|
ReturnTimestamp, HaveReadInt2, !HaveParseTreeMaps, !IO),
|
|
(
|
|
HaveReadInt2 = have_module(_FileName, ParseTreeInt2, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
MaybeTimestamp, Errors),
|
|
GrabbedFile = gf_int2(ParseTreeInt2, ReadWhy2),
|
|
module_baggage_add_grabbed_file(ModuleName, GrabbedFile, !Baggage),
|
|
(
|
|
( ReadWhy2 = rwi2_int_use
|
|
; ReadWhy2 = rwi2_imp_use
|
|
; ReadWhy2 = rwi2_abstract
|
|
),
|
|
IndirectIntSpec = indirect_int2(ParseTreeInt2, ReadWhy2),
|
|
aug_compilation_unit_add_indirect_int2_spec(IndirectIntSpec,
|
|
!AugCompUnit)
|
|
;
|
|
ReadWhy2 = rwi2_opt,
|
|
IntForOptSpec = for_opt_int2(ParseTreeInt2, ReadWhy2),
|
|
aug_compilation_unit_add_int_for_opt_spec(IntForOptSpec,
|
|
!AugCompUnit)
|
|
),
|
|
map.foldl2(get_uses, ParseTreeInt2 ^ pti2_use_map,
|
|
set.init, IntUses, set.init, ImpUses),
|
|
maybe_record_interface_timestamp(ModuleName, ifk_int2,
|
|
recomp_avail_imp_use, MaybeTimestamp, !Baggage),
|
|
aug_compilation_unit_maybe_add_module_version_numbers(ModuleName,
|
|
ParseTreeInt2 ^ pti2_maybe_version_numbers, !AugCompUnit)
|
|
;
|
|
HaveReadInt2 = have_not_read_module(_FileName, Errors),
|
|
set.init(IntUses),
|
|
set.init(ImpUses)
|
|
),
|
|
module_baggage_add_errors(Errors, !Baggage).
|
|
|
|
:- pred grab_module_int3_file(io.text_output_stream::in, globals::in,
|
|
read_why_int3::in, module_name::in, set(module_name)::out,
|
|
have_parse_tree_maps::in, have_parse_tree_maps::out,
|
|
module_baggage::in, module_baggage::out,
|
|
aug_make_int_unit::in, aug_make_int_unit::out, io::di, io::uo) is det.
|
|
|
|
grab_module_int3_file(ProgressStream, Globals, ReadWhy3, ModuleName,
|
|
IntImports, !HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO) :-
|
|
do_we_need_timestamps(!.Baggage, ReturnTimestamp),
|
|
maybe_read_module_int3(ProgressStream, Globals, do_search, ModuleName,
|
|
ReturnTimestamp, HaveReadInt3, !HaveParseTreeMaps, !IO),
|
|
(
|
|
HaveReadInt3 = have_module(_FileName, ParseTreeInt3, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
MaybeTimestamp, Errors),
|
|
GrabbedFile = gf_int3(ParseTreeInt3, ReadWhy3),
|
|
module_baggage_add_grabbed_file(ModuleName, GrabbedFile, !Baggage),
|
|
(
|
|
(
|
|
ReadWhy3 = rwi3_direct_ancestor_import,
|
|
RecompAvail = recomp_avail_int_import
|
|
;
|
|
ReadWhy3 = rwi3_direct_int_import,
|
|
RecompAvail = recomp_avail_int_import
|
|
;
|
|
ReadWhy3 = rwi3_direct_imp_import,
|
|
RecompAvail = recomp_avail_imp_import
|
|
;
|
|
ReadWhy3 = rwi3_direct_ancestor_use,
|
|
RecompAvail = recomp_avail_int_use
|
|
;
|
|
ReadWhy3 = rwi3_direct_int_use,
|
|
RecompAvail = recomp_avail_int_use
|
|
;
|
|
ReadWhy3 = rwi3_direct_imp_use,
|
|
RecompAvail = recomp_avail_imp_use
|
|
;
|
|
ReadWhy3 = rwi3_direct_int_use_imp_import,
|
|
RecompAvail = recomp_avail_int_use_imp_import
|
|
),
|
|
DirectIntSpec = direct_int3(ParseTreeInt3, ReadWhy3),
|
|
aug_make_int_unit_add_direct_int3_spec(DirectIntSpec,
|
|
!AugMakeIntUnit)
|
|
;
|
|
(
|
|
ReadWhy3 = rwi3_indirect_int_use,
|
|
RecompAvail = recomp_avail_int_use
|
|
;
|
|
ReadWhy3 = rwi3_indirect_imp_use,
|
|
RecompAvail = recomp_avail_imp_use
|
|
),
|
|
IndirectIntSpec = indirect_int3(ParseTreeInt3, ReadWhy3),
|
|
aug_make_int_unit_add_indirect_int3_spec(IndirectIntSpec,
|
|
!AugMakeIntUnit)
|
|
),
|
|
IntImportMap = ParseTreeInt3 ^ pti3_int_import_map,
|
|
map.keys_as_set(IntImportMap, IntImports),
|
|
maybe_record_interface_timestamp(ModuleName, ifk_int3, RecompAvail,
|
|
MaybeTimestamp, !Baggage)
|
|
;
|
|
HaveReadInt3 = have_not_read_module(_FileName, Errors),
|
|
set.init(IntImports)
|
|
),
|
|
module_baggage_add_errors(Errors, !Baggage).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type read_decision
|
|
---> decided_not_to_read
|
|
; decided_to_read.
|
|
|
|
:- pred maybe_log_augment_decision(io.text_output_stream::in, string::in,
|
|
int_file_kind::in, T::in, module_name::in, read_decision::in,
|
|
io::di, io::uo) is det.
|
|
% Inlining calls to this predicate effectively optimizes it away
|
|
% if the trace condition is not met, as it usually won't be.
|
|
:- pragma inline(pred(maybe_log_augment_decision/8)).
|
|
|
|
maybe_log_augment_decision(ProgressStream, Why, IntFileKind, ReadWhy,
|
|
ModuleName, Read, IO, IO) :-
|
|
trace [compile_time(flag("log_augment_decisions")),
|
|
runtime(env("LOG_AUGMENT_DECISION")), io(!TIO)]
|
|
(
|
|
ModuleNameStr = sym_name_to_string(ModuleName),
|
|
( IntFileKind = ifk_int0, ExtStr = ".int0"
|
|
% We print ".int1" instead of the correct ".int" for alignment.
|
|
; IntFileKind = ifk_int1, ExtStr = ".int1"
|
|
; IntFileKind = ifk_int2, ExtStr = ".int2"
|
|
; IntFileKind = ifk_int3, ExtStr = ".int3"
|
|
),
|
|
WhyStr = string.string(ReadWhy),
|
|
(
|
|
Read = decided_not_to_read,
|
|
ReadStr = "decided not to read"
|
|
;
|
|
Read = decided_to_read,
|
|
ReadStr = "decided to read"
|
|
),
|
|
io.format(ProgressStream, "AUGMENT_LOG %s, %s, %s, %s: %s\n",
|
|
[s(Why), s(ModuleNameStr), s(ExtStr), s(WhyStr), s(ReadStr)], !TIO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_record_interface_timestamp(module_name::in, int_file_kind::in,
|
|
recomp_avail::in, maybe(timestamp)::in,
|
|
module_baggage::in, module_baggage::out) is det.
|
|
|
|
maybe_record_interface_timestamp(ModuleName, IntFileKind, RecompAvail,
|
|
MaybeTimestamp, !Baggage) :-
|
|
MaybeTimestampMap = !.Baggage ^ mb_maybe_timestamp_map,
|
|
(
|
|
MaybeTimestampMap = yes(TimestampMap0),
|
|
(
|
|
MaybeTimestamp = yes(Timestamp),
|
|
FileKind = fk_int(IntFileKind),
|
|
TimestampInfo = module_timestamp(FileKind, Timestamp, RecompAvail),
|
|
map.set(ModuleName, TimestampInfo, TimestampMap0, TimestampMap),
|
|
!Baggage ^ mb_maybe_timestamp_map := yes(TimestampMap)
|
|
;
|
|
MaybeTimestamp = no
|
|
)
|
|
;
|
|
MaybeTimestampMap = no
|
|
).
|
|
|
|
:- pred do_we_need_timestamps(module_baggage::in,
|
|
maybe_return_timestamp::out) is det.
|
|
|
|
do_we_need_timestamps(Baggage, MaybeReturnTimestamp) :-
|
|
MaybeTimestampMap = Baggage ^ mb_maybe_timestamp_map,
|
|
(
|
|
MaybeTimestampMap = yes(_),
|
|
MaybeReturnTimestamp = do_return_timestamp
|
|
;
|
|
MaybeTimestampMap = no,
|
|
MaybeReturnTimestamp = do_not_return_timestamp
|
|
).
|
|
|
|
:- pred module_baggage_add_grabbed_file(module_name::in, grabbed_file::in,
|
|
module_baggage::in, module_baggage::out) is det.
|
|
|
|
module_baggage_add_grabbed_file(ModuleName, FileWhy, !Baggage) :-
|
|
GrabbedFileMap0 = !.Baggage ^ mb_grabbed_file_map,
|
|
% We could be adding a new entry to the map, or overwriting an existing
|
|
% entry. XXX Why would we overwrite an entry?
|
|
map.set(ModuleName, FileWhy, GrabbedFileMap0, GrabbedFileMap),
|
|
!Baggage ^ mb_grabbed_file_map := GrabbedFileMap.
|
|
|
|
:- pred module_baggage_add_nonfatal_specs(list(error_spec)::in,
|
|
module_baggage::in, module_baggage::out) is det.
|
|
|
|
module_baggage_add_nonfatal_specs(NewSpecs, !Baggage) :-
|
|
Errors0 = !.Baggage ^ mb_errors,
|
|
NonFatalErrorSpecs0 = Errors0 ^ rm_nonfatal_error_specs,
|
|
NonFatalErrorSpecs = NewSpecs ++ NonFatalErrorSpecs0,
|
|
Errors = Errors0 ^ rm_nonfatal_error_specs := NonFatalErrorSpecs,
|
|
!Baggage ^ mb_errors := Errors.
|
|
|
|
:- pred module_baggage_add_errors(read_module_errors::in,
|
|
module_baggage::in, module_baggage::out) is det.
|
|
|
|
module_baggage_add_errors(Errors1, !Baggage) :-
|
|
Errors0 = !.Baggage ^ mb_errors,
|
|
Errors0 = read_module_errors(FatalErrors0, FatalErrorSpecs0,
|
|
NonFatalErrors0, NonFatalErrorSpecs0, WarningSpecs0),
|
|
Errors1 = read_module_errors(FatalErrors1, FatalErrorSpecs1,
|
|
NonFatalErrors1, NonFatalErrorSpecs1, WarningSpecs1),
|
|
FatalErrors = set.union(FatalErrors0, FatalErrors1),
|
|
FatalErrorSpecs = FatalErrorSpecs0 ++ FatalErrorSpecs1,
|
|
NonFatalErrors = set.union(NonFatalErrors0, NonFatalErrors1),
|
|
NonFatalErrorSpecs = NonFatalErrorSpecs0 ++ NonFatalErrorSpecs1,
|
|
WarningSpecs = WarningSpecs0 ++ WarningSpecs1,
|
|
Errors = read_module_errors(FatalErrors, FatalErrorSpecs,
|
|
NonFatalErrors, NonFatalErrorSpecs, WarningSpecs),
|
|
!Baggage ^ mb_errors := Errors.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred keep_only_unused_and_reuse_pragmas_in_parse_tree_plain_opt(
|
|
maybe_opt_unused_args_intermod::in, bool::in,
|
|
parse_tree_plain_opt::in, parse_tree_plain_opt::out) is det.
|
|
|
|
keep_only_unused_and_reuse_pragmas_in_parse_tree_plain_opt(
|
|
KeepUnusedArgs, KeepReuses, ParseTreePlainOpt0, ParseTreePlainOpt) :-
|
|
ParseTreePlainOpt0 = parse_tree_plain_opt(ModuleName, ModuleNameContext,
|
|
_UsedModuleNames, _FIMSpecs, _TypeDefns, _ForeignEnums,
|
|
_InstDefns, _ModeDefns, _TypeClasses, _Instances,
|
|
_PredDecls, _ModeDecls, _Clauses, _ForeignProcs, _Promises,
|
|
_DeclMarkers, _ImplMarkers, _TypeSpecs,
|
|
UnusedArgs0, _TermInfos, _Term2Infos,
|
|
_Exceptions, _Trailings, _MMTablings, _Sharings, Reuses0),
|
|
(
|
|
KeepUnusedArgs = opt_unused_args_intermod,
|
|
UnusedArgs = UnusedArgs0
|
|
;
|
|
KeepUnusedArgs = do_not_opt_unused_args_intermod,
|
|
UnusedArgs = []
|
|
),
|
|
(
|
|
KeepReuses = yes,
|
|
Reuses = Reuses0
|
|
;
|
|
KeepReuses = no,
|
|
Reuses = []
|
|
),
|
|
ParseTreePlainOpt = parse_tree_plain_opt(ModuleName, ModuleNameContext,
|
|
map.init, set.init, [], [], [], [], [], [], [], [], [], [], [],
|
|
[], [], [], UnusedArgs, [], [], [], [], [], [], Reuses).
|
|
|
|
:- pred read_plain_opt_files(io.text_output_stream::in, globals::in,
|
|
bool::in, bool::in, list(module_name)::in, set(module_name)::in,
|
|
cord(parse_tree_plain_opt)::in, cord(parse_tree_plain_opt)::out,
|
|
set(module_name)::in, set(module_name)::out,
|
|
cord(implicit_avail_needs)::in, cord(implicit_avail_needs)::out,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
maybe_opt_file_error::in, maybe_opt_file_error::out,
|
|
io::di, io::uo) is det.
|
|
|
|
read_plain_opt_files(_, _, _, _, [], _, !ParseTreePlainOptsCord,
|
|
!ExplicitDeps, !ImplicitNeeds, !Specs, !OptError, !IO).
|
|
read_plain_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ReadOptFilesTransitively, [ModuleName | ModuleNames0],
|
|
DontQueueOptModules0, !ParseTreePlainOptsCord,
|
|
!ExplicitDeps, !ImplicitNeeds, !Specs, !OptError, !IO) :-
|
|
read_module_plain_opt(ProgressStream, Globals, ModuleName,
|
|
HaveReadPlainOpt, !IO),
|
|
(
|
|
HaveReadPlainOpt = have_module(_FileName, ParseTreePlainOpt, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
_, ModuleErrors),
|
|
cord.snoc(ParseTreePlainOpt, !ParseTreePlainOptsCord),
|
|
update_opt_error_status_on_success(ModuleErrors, !Specs, !OptError),
|
|
|
|
get_explicit_and_implicit_avail_needs_in_parse_tree_plain_opt(
|
|
ParseTreePlainOpt, ParseTreeExplicitDeps, ParseTreeImplicitNeeds),
|
|
set.union(ParseTreeExplicitDeps, !ExplicitDeps),
|
|
cord.snoc(ParseTreeImplicitNeeds, !ImplicitNeeds),
|
|
(
|
|
ReadOptFilesTransitively = yes,
|
|
compute_implicit_avail_needs(Globals, ParseTreeImplicitNeeds,
|
|
ParseTreeImplicitDeps),
|
|
set.union(ParseTreeExplicitDeps, ParseTreeImplicitDeps,
|
|
ParseTreeDeps),
|
|
set.difference(ParseTreeDeps, DontQueueOptModules0, NewDeps),
|
|
ModuleNames1 = set.to_sorted_list(NewDeps) ++ ModuleNames0,
|
|
set.union(NewDeps, DontQueueOptModules0, DontQueueOptModules1)
|
|
;
|
|
ReadOptFilesTransitively = no,
|
|
ModuleNames1 = ModuleNames0,
|
|
DontQueueOptModules1 = DontQueueOptModules0
|
|
)
|
|
;
|
|
HaveReadPlainOpt = have_not_read_module(FileName, ModuleErrors),
|
|
update_opt_error_status_on_failure(Globals, warn_missing_opt_files,
|
|
FileName, ModuleErrors, !Specs, !OptError),
|
|
ModuleNames1 = ModuleNames0,
|
|
DontQueueOptModules1 = DontQueueOptModules0
|
|
),
|
|
|
|
maybe_write_out_errors(ProgressStream, VeryVerbose, Globals, !Specs, !IO),
|
|
read_plain_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ReadOptFilesTransitively, ModuleNames1, DontQueueOptModules1,
|
|
!ParseTreePlainOptsCord, !ExplicitDeps, !ImplicitNeeds,
|
|
!Specs, !OptError, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred read_trans_opt_files(io.text_output_stream::in, globals::in,
|
|
bool::in, list(module_name)::in,
|
|
cord(parse_tree_trans_opt)::in, cord(parse_tree_trans_opt)::out,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
maybe_opt_file_error::in, maybe_opt_file_error::out,
|
|
io::di, io::uo) is det.
|
|
|
|
read_trans_opt_files(_, _, _, [], !ParseTreeTransOpts, !Specs, !Error, !IO).
|
|
read_trans_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
[ModuleName | ModuleNames], !ParseTreeTransOptsCord,
|
|
!Specs, !OptError, !IO) :-
|
|
read_module_trans_opt(ProgressStream, Globals, ModuleName,
|
|
HaveReadTransOpt, !IO),
|
|
(
|
|
HaveReadTransOpt = have_module(_FileName, ParseTreeTransOpt, Source),
|
|
have_parse_tree_source_get_maybe_timestamp_errors(Source,
|
|
_, ModuleErrors),
|
|
cord.snoc(ParseTreeTransOpt, !ParseTreeTransOptsCord),
|
|
update_opt_error_status_on_success(ModuleErrors, !Specs, !OptError)
|
|
;
|
|
HaveReadTransOpt = have_not_read_module(FileName, Errors),
|
|
update_opt_error_status_on_failure(Globals,
|
|
warn_missing_trans_opt_files, FileName, Errors, !Specs, !OptError)
|
|
),
|
|
maybe_write_out_errors(ProgressStream, VeryVerbose, Globals, !Specs, !IO),
|
|
|
|
read_trans_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ModuleNames, !ParseTreeTransOptsCord, !Specs, !OptError, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% update_opt_error_status_on_failure(Globals, WarnOption, FileName,
|
|
% !Specs, !Error):
|
|
%
|
|
% Process the failure of opening a .opt or .trans_opt file.
|
|
%
|
|
% Our caller does not pass us the error message for that failure,
|
|
% since we always construct our own error message.
|
|
% XXX This may not be the best course of action.
|
|
%
|
|
% A missing `.opt' or `.trans_opt' file is only a fatal error if
|
|
% `--halt-at-warn' was passed the compiler together with
|
|
% `--warn-missing-opt-files' or `--warn-missing-trans-opt-files'
|
|
% respectively.
|
|
%
|
|
:- pred update_opt_error_status_on_failure(globals::in, option::in,
|
|
file_name::in, read_module_errors::in,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
maybe_opt_file_error::in, maybe_opt_file_error::out) is det.
|
|
|
|
update_opt_error_status_on_failure(Globals, WarnOption, FileName,
|
|
ReadModuleErrors, !Specs, Error, Error) :-
|
|
% We get here if we couldn't find and/or open the file.
|
|
% ModuleErrors ^ rm_fatal_error_specs will already contain
|
|
% an error_severity error_spec about that, with more details
|
|
% than the message we generate below, but the test case
|
|
% hard_coded/intermod_unused_args insists on there being no error,
|
|
% only a warning with the text below. That is why we do not add
|
|
% any error_specs from ModuleErrors to !Specs here.
|
|
%
|
|
% I (zs) don't know whether we should add a version of ModuleSpecs
|
|
% with downgraded severity to !Specs instead of the Spec we generate
|
|
% below.
|
|
globals.lookup_bool_option(Globals, WarnOption, WarnOptionValue),
|
|
(
|
|
WarnOptionValue = no
|
|
;
|
|
WarnOptionValue = yes,
|
|
Pieces = [words("Warning: cannot open"), quote(FileName),
|
|
suffix("."), nl],
|
|
FatalErrors = ReadModuleErrors ^ rm_fatal_errors,
|
|
( if set.contains(FatalErrors, frme_could_not_find_file) then
|
|
Phase = phase_find_files(FileName)
|
|
else
|
|
Phase = phase_read_files
|
|
),
|
|
Spec = no_ctxt_spec($pred, severity_warning(WarnOption),
|
|
Phase, Pieces),
|
|
!:Specs = [Spec | !.Specs]
|
|
).
|
|
% NOTE: We do NOT update !Error, since a missing optimization
|
|
% interface file is not necessarily an error.
|
|
|
|
% update_opt_error_status_on_success(ModuleErrors, !Specs, !Error):
|
|
%
|
|
% Work out whether any errors have occurred while reading
|
|
% a .opt or .trans_opt file, and update !Error accordingly.
|
|
% Note that we can ignore *not finding* a .opt or .trans_opt file,
|
|
% a situation handled by update_opt_error_status_on_failure,
|
|
% finding any error, whether syntax or semantic, inside one of these files
|
|
% that does exist is always fatal. This is because it indicates that
|
|
% - either the Mercury compiler invocation that created it had a bug,
|
|
% - or that the file has been tampered with later.
|
|
%
|
|
:- pred update_opt_error_status_on_success(read_module_errors::in,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
maybe_opt_file_error::in, maybe_opt_file_error::out) is det.
|
|
|
|
update_opt_error_status_on_success(ModuleErrors, !Specs, !Error) :-
|
|
FatalErrors = ModuleErrors ^ rm_fatal_errors,
|
|
NonFatalErrors0 = ModuleErrors ^ rm_nonfatal_errors,
|
|
set.delete(rme_nec, NonFatalErrors0, NonFatalErrors),
|
|
( if
|
|
set.is_empty(FatalErrors),
|
|
set.is_empty(NonFatalErrors)
|
|
then
|
|
% ModuleSpecs contains no errors we have traditionally recorded
|
|
% as a separately classified error. It could contain
|
|
%
|
|
% - errors we have generated error messages for but for which
|
|
% we have not recorded an error category (these are the errors
|
|
% whose category we now record as Not Elsewhere Classified,
|
|
% or rme_nec), and
|
|
%
|
|
% - warnings.
|
|
%
|
|
% Not adding either of those to !Specs preserves old behavior.
|
|
true
|
|
else
|
|
!:Specs = get_read_module_specs(ModuleErrors) ++ !.Specs,
|
|
!:Error = opt_file_error
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred aug_compilation_unit_add_ancestor_int_spec(ancestor_int_spec::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_direct_int1_spec(direct_int1_spec::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_indirect_int2_spec(indirect_int2_spec::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_plain_opt(parse_tree_plain_opt::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_trans_opt(parse_tree_trans_opt::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_int_for_opt_spec(int_for_opt_spec::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_add_type_repn_spec(type_repn_spec::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
:- pred aug_compilation_unit_maybe_add_module_version_numbers(
|
|
module_name::in, maybe_version_numbers::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
aug_compilation_unit_add_ancestor_int_spec(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_ancestor_ints,
|
|
X = ancestor_int0(PT0, _),
|
|
MN = PT0 ^ pti0_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_ancestor_ints := Map.
|
|
|
|
aug_compilation_unit_add_direct_int1_spec(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_direct_int1s,
|
|
X = direct_int1(PT1, _), MN = PT1 ^ pti1_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_direct_int1s := Map.
|
|
|
|
aug_compilation_unit_add_indirect_int2_spec(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_indirect_int2s,
|
|
X = indirect_int2(PT2, _), MN = PT2 ^ pti2_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_indirect_int2s := Map.
|
|
|
|
aug_compilation_unit_add_plain_opt(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_plain_opts,
|
|
MN = X ^ ptpo_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_plain_opts := Map.
|
|
|
|
aug_compilation_unit_add_trans_opt(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_trans_opts,
|
|
MN = X ^ ptto_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_trans_opts := Map.
|
|
|
|
aug_compilation_unit_add_int_for_opt_spec(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_int_for_opts,
|
|
( X = for_opt_int0(PT0, _), MN = PT0 ^ pti0_module_name
|
|
; X = for_opt_int1(PT1, _), MN = PT1 ^ pti1_module_name
|
|
; X = for_opt_int2(PT2, _), MN = PT2 ^ pti2_module_name
|
|
),
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_int_for_opts := Map.
|
|
|
|
aug_compilation_unit_add_type_repn_spec(X, !AugCompUnit) :-
|
|
Map0 = !.AugCompUnit ^ acu_type_repns,
|
|
X = type_repn_spec_int1(PT1), MN = PT1 ^ pti1_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugCompUnit ^ acu_type_repns := Map.
|
|
|
|
aug_compilation_unit_maybe_add_module_version_numbers(ModuleName,
|
|
MaybeVersionNumbers, !AugCompUnit) :-
|
|
(
|
|
MaybeVersionNumbers = no_version_numbers
|
|
;
|
|
MaybeVersionNumbers = version_numbers(VersionNumbers),
|
|
ModuleVersionNumbersMap0 = !.AugCompUnit ^ acu_item_version_map,
|
|
map.det_insert(ModuleName, VersionNumbers,
|
|
ModuleVersionNumbersMap0, ModuleVersionNumbersMap),
|
|
!AugCompUnit ^ acu_item_version_map := ModuleVersionNumbersMap
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred init_aug_make_int_unit(parse_tree_module_src::in,
|
|
aug_make_int_unit::out) is det.
|
|
|
|
init_aug_make_int_unit(ParseTreeModuleSrc, AugMakeIntUnit) :-
|
|
DelayedSpecs = [],
|
|
map.init(AncestorIntSpecs),
|
|
map.init(DirectIntSpecs),
|
|
map.init(IndirectIntSpecs),
|
|
map.init(VersionNumbers),
|
|
AugMakeIntUnit = aug_make_int_unit(ParseTreeModuleSrc, DelayedSpecs,
|
|
AncestorIntSpecs, DirectIntSpecs, IndirectIntSpecs, VersionNumbers).
|
|
|
|
%---------------------%
|
|
|
|
:- pred aug_make_int_unit_add_ancestor_int(parse_tree_int0::in,
|
|
aug_make_int_unit::in, aug_make_int_unit::out) is det.
|
|
:- pred aug_make_int_unit_add_direct_int3_spec(direct_int3_spec::in,
|
|
aug_make_int_unit::in, aug_make_int_unit::out) is det.
|
|
:- pred aug_make_int_unit_add_indirect_int3_spec(indirect_int3_spec::in,
|
|
aug_make_int_unit::in, aug_make_int_unit::out) is det.
|
|
:- pred aug_make_int_unit_maybe_add_module_version_numbers(
|
|
module_name::in, maybe_version_numbers::in,
|
|
aug_make_int_unit::in, aug_make_int_unit::out) is det.
|
|
|
|
%---------------------%
|
|
|
|
aug_make_int_unit_add_ancestor_int(PT0, !AugMakeIntUnit) :-
|
|
Map0 = !.AugMakeIntUnit ^ amiu_ancestor_ints,
|
|
MN = PT0 ^ pti0_module_name,
|
|
map.det_insert(MN, PT0, Map0, Map),
|
|
!AugMakeIntUnit ^ amiu_ancestor_ints := Map.
|
|
|
|
aug_make_int_unit_add_direct_int3_spec(X, !AugMakeIntUnit) :-
|
|
Map0 = !.AugMakeIntUnit ^ amiu_direct_int3s,
|
|
X = direct_int3(PT3, _), MN = PT3 ^ pti3_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugMakeIntUnit ^ amiu_direct_int3s := Map.
|
|
|
|
aug_make_int_unit_add_indirect_int3_spec(X, !AugMakeIntUnit) :-
|
|
Map0 = !.AugMakeIntUnit ^ amiu_indirect_int3s,
|
|
X = indirect_int3(PT3, _), MN = PT3 ^ pti3_module_name,
|
|
map.det_insert(MN, X, Map0, Map),
|
|
!AugMakeIntUnit ^ amiu_indirect_int3s := Map.
|
|
|
|
aug_make_int_unit_maybe_add_module_version_numbers(ModuleName,
|
|
MaybeVersionNumbers, !AugMakeIntUnit) :-
|
|
(
|
|
MaybeVersionNumbers = no_version_numbers
|
|
;
|
|
MaybeVersionNumbers = version_numbers(VersionNumbers),
|
|
ModuleVersionNumbersMap0 = !.AugMakeIntUnit ^ amiu_item_version_map,
|
|
map.det_insert(ModuleName, VersionNumbers,
|
|
ModuleVersionNumbersMap0, ModuleVersionNumbersMap),
|
|
!AugMakeIntUnit ^ amiu_item_version_map := ModuleVersionNumbersMap
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred dump_modules(io.text_output_stream::in, set(module_name)::in,
|
|
io::di, io::uo) is det.
|
|
:- pragma consider_used(pred(dump_modules/4)).
|
|
|
|
dump_modules(Stream, ModuleNames, !IO) :-
|
|
ModuleNameStrs =
|
|
set.to_sorted_list(set.map(sym_name_to_string, ModuleNames)),
|
|
list.foldl(io.write_line(Stream), ModuleNameStrs, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.grab_modules.
|
|
%---------------------------------------------------------------------------%
|