mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
This is another move towards making it impossible for the compiler
to stop due to the presence of an error *without* printing a diagnostic
about that error.
compiler/grab_modules.m:
Some of the errors that this module are intended to block the compiler
from continuing on to semantic analysis, and some are not. We used
to make the distinction by returning a flag saying "some of these
are blocking errors", but the list of diagnostics that contained
these blocking errors
- contained a list of error_specs reporting *both* kinds of errors, and
- was not returned alongside the flag, but instead hidden inside
the module baggage, making it hard to find, and easy to ignore.
Change this to computing two lists of error_specs: one for blocking errors,
and one for nonblocking ones. Return the former explicitly, keeping the
latter in the baggage. This design lets the code that stops execution
before semantic analysis to test for the list of blocking errors
being non-empty, which makes printing them the easy thing to do.
Delete the code that, with --very-verbose, wrote out any error_specs
we generated during the processing of a .opt or .trans_opt file
immediately after that processing. The reason is that
- if we print those error_specs out and then do not return them
to mercury_compile_make_hlds.m, then mercury_compile_make_hlds.m
will be making decisions on incomplete and therefore incorrect data,
while
- if we print those error_specs out and *also* return them, then
- either those diagnostics will be printed twice, or
- we need to implement a new system whereby write_error_spec.m
keeps a database of the diagnostics it has already printed,
and simply skips printing any repeats.
Neither of those alternative is palatable, and since in several
decades, I have never needed such immediate printing of diagnostics,
losing that capability is not really an issue.
Fix some relics of the era when the data structures that were
module_baggage's predecessors could not distinguish between fatal
and nonfatal errors.
compiler/mercury_compile_make_hlds.m:
For now, make the new code in grab_modules.m work with the existing
decision making code. Changing that is future work, since it requires
changes to other compiler components as well.
1739 lines
78 KiB
Mathematica
1739 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.error_spec.
|
|
:- 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.
|
|
|
|
% grab_plain_opt_and_int_for_opt_files(ProgressStream, Globals,
|
|
% BlockingSpecs, !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,
|
|
globals::in, list(error_spec)::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,
|
|
% BlockingSpecs, !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, list(error_spec)::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.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 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, Globals,
|
|
!:BlockingSpecs, !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,
|
|
[], NonBlockingSpecs0, [], !:BlockingSpecs, !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],
|
|
report_any_errors_in_read_opt_file(OwnOptModuleErrors,
|
|
!BlockingSpecs),
|
|
NonBlockingSpecs = NonBlockingSpecs0
|
|
;
|
|
HaveReadOwnPlainOpt0 =
|
|
have_not_read_module(OwnOptFileName, OwnOptModuleErrors),
|
|
ParseTreePlainOpts = ParseTreePlainOpts0,
|
|
report_cannot_read_opt_file(Globals, warn_missing_opt_files,
|
|
OwnOptFileName, OwnOptModuleErrors,
|
|
NonBlockingSpecs0, NonBlockingSpecs)
|
|
)
|
|
else
|
|
ParseTreePlainOpts = ParseTreePlainOpts0,
|
|
NonBlockingSpecs = NonBlockingSpecs0
|
|
),
|
|
|
|
list.foldl(aug_compilation_unit_add_plain_opt, ParseTreePlainOpts,
|
|
!AugCompUnit),
|
|
|
|
% 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/.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),
|
|
|
|
% Return the diagnostics that describe the things that went wrong
|
|
% in a way that prevents us continuing on to the semantic analysis passes.
|
|
%
|
|
% Instead of returning a list of error_specs, we used to return a flag
|
|
% meaning "do not continue to semantic analysis". We set this flag to its
|
|
% "do not continue" value not just when ModuleErrors ^ rm_fatal_errors
|
|
% was nonempty, but also when ModuleErrors ^ rm_nonfatal_errors was
|
|
% nonempty. This was a legacy of the time when we stored fatal and
|
|
% nonfatal errors mixed together.
|
|
ModuleErrors = !.Baggage ^ mb_errors,
|
|
!:BlockingSpecs =
|
|
ModuleErrors ^ rm_fatal_error_specs ++
|
|
% ModuleErrors ^ rm_nonfatal_error_specs ++ see above
|
|
!.BlockingSpecs,
|
|
|
|
% This adds NonBlockingSpecs to ModuleErrors ^ rm_nonfatal_error_specs.
|
|
% If we ever want to go back to the old behavior of considering
|
|
% ModuleErrors ^ rm_nonfatal_error_specs being nonempty as grounds for
|
|
% stopping compiler execution before semantic analysis, then we would
|
|
% want the computation of !:BlockingSpecs to use the value of that field
|
|
% before this addition.
|
|
%
|
|
% NOTE Another legacy of the time when we stored fatal and nonfatal
|
|
% errors mixed together was that previously, we also added the original
|
|
% !.BlockingSpecs (i.e. the version from before adding
|
|
% ModuleErrors ^ rm_fatal_error_specs) to the baggage as well.
|
|
module_baggage_add_nonfatal_specs(NonBlockingSpecs, !Baggage).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
grab_trans_opt_files(ProgressStream, Globals, TransOptModuleNames,
|
|
BlockingSpecs, !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),
|
|
|
|
read_trans_opt_files(ProgressStream, Globals, TransOptModuleNames,
|
|
cord.init, ParseTreeTransOptsCord,
|
|
[], NonBlockingSpecs, [], BlockingSpecs, !IO),
|
|
list.foldl(aug_compilation_unit_add_trans_opt,
|
|
cord.list(ParseTreeTransOptsCord), !AugCompUnit),
|
|
module_baggage_add_nonfatal_specs(NonBlockingSpecs, !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,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
read_plain_opt_files(_, _, _, _, [], _, !ParseTreePlainOptsCord,
|
|
!ExplicitDeps, !ImplicitNeeds, !NonBlockingSpecs, !BlockingSpecs, !IO).
|
|
read_plain_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ReadOptFilesTransitively, [ModuleName | ModuleNames0],
|
|
DontQueueOptModules0, !ParseTreePlainOptsCord,
|
|
!ExplicitDeps, !ImplicitNeeds,
|
|
!NonBlockingSpecs, !BlockingSpecs, !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),
|
|
report_any_errors_in_read_opt_file(ModuleErrors, !BlockingSpecs),
|
|
|
|
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),
|
|
report_cannot_read_opt_file(Globals, warn_missing_opt_files,
|
|
FileName, ModuleErrors, !NonBlockingSpecs),
|
|
ModuleNames1 = ModuleNames0,
|
|
DontQueueOptModules1 = DontQueueOptModules0
|
|
),
|
|
|
|
read_plain_opt_files(ProgressStream, Globals, VeryVerbose,
|
|
ReadOptFilesTransitively, ModuleNames1, DontQueueOptModules1,
|
|
!ParseTreePlainOptsCord, !ExplicitDeps, !ImplicitNeeds,
|
|
!NonBlockingSpecs, !BlockingSpecs, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred read_trans_opt_files(io.text_output_stream::in, globals::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,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
read_trans_opt_files(_, _, [], !ParseTreeTransOpts,
|
|
!NonBlockingSpecs, !BlockingSpecs, !IO).
|
|
read_trans_opt_files(ProgressStream, Globals, [ModuleName | ModuleNames],
|
|
!ParseTreeTransOptsCord, !NonBlockingSpecs, !BlockingSpecs, !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),
|
|
report_any_errors_in_read_opt_file(ModuleErrors, !BlockingSpecs)
|
|
;
|
|
HaveReadTransOpt = have_not_read_module(FileName, ReadErrors),
|
|
WarnOpt = warn_missing_trans_opt_files,
|
|
report_cannot_read_opt_file(Globals, WarnOpt, FileName,
|
|
ReadErrors, !NonBlockingSpecs)
|
|
),
|
|
read_trans_opt_files(ProgressStream, Globals, ModuleNames,
|
|
!ParseTreeTransOptsCord, !NonBlockingSpecs, !BlockingSpecs, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% report_cannot_read_opt_file(Globals, WarnOption, FileName,
|
|
% !Specs):
|
|
%
|
|
% 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 report_cannot_read_opt_file(globals::in, option::in,
|
|
file_name::in, read_module_errors::in,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
report_cannot_read_opt_file(Globals, WarnOption, FileName,
|
|
ReadModuleErrors, !NonBlockingSpecs) :-
|
|
% 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),
|
|
!:NonBlockingSpecs = [Spec | !.NonBlockingSpecs]
|
|
).
|
|
% NOTE: We do NOT update !BlockingSpecs, since a missing optimization
|
|
% interface file is not necessarily an error.
|
|
|
|
% report_any_errors_in_read_opt_file(ModuleErrors, !BlockingSpecs):
|
|
%
|
|
% Work out whether any errors have occurred while reading
|
|
% a .opt or .trans_opt file, and update !BlockingSpecs accordingly.
|
|
% Note that
|
|
%
|
|
% - we can ignore *not finding* a .opt or .trans_opt file,
|
|
% a situation handled by report_cannot_read_opt_file, but
|
|
%
|
|
% - 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 report_any_errors_in_read_opt_file(read_module_errors::in,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
report_any_errors_in_read_opt_file(ModuleErrors, !BlockingSpecs) :-
|
|
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
|
|
ModuleSpecs = get_read_module_specs(ModuleErrors),
|
|
expect_not(unify(ModuleSpecs, []), $pred, "ModuleSpecs = []"),
|
|
!:BlockingSpecs = ModuleSpecs ++ !.BlockingSpecs
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- 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.
|
|
%---------------------------------------------------------------------------%
|