mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 12:53:53 +00:00
The ultimate purpose of this diff is to prepare for future improvements
in type representations, allowing values of some data types to be represented
more compactly than up to now.
The main way this diff does that is by creating a separate pass for deciding
how values of each type should be represented. We have traditionally decided
data representations for each type as its type definition was processed
during the make_hlds pass, but these decisions were always tentative,
and could be overridden later, e.g. when we processed foreign_type or
foreign_enum pragmas for the type. This dispersed decision making algorithm
is hard to understand, and therefore to change.
This diff centralizes decisions about type representations in a separate
pass that does nothing else. It leaves the algorithm distributed among
several files (du_type_layout.m, make_tags.m, and add_foreign_enum.m) for now,
to make reviewing this diff easier, but soon after it is committed I intend
to move all the relevant code to du_type_layout.m, to centralize the decision
code in "space" as well as in time.
For the reason why this pass runs before any of the semantic analysis
passes, instead of after all of them as I originally intended and as we
discussed on m-dev in late october 2017, see the big comment at the start of
du_type_layout.m.
As per another part of that same discussion on m-dev, this diff
makes a start on implementing a new type of item, the type_repn item,
which is intended *only* to be used in compiler-generated interface files,
*not* in source files. It is only a start because we can use these items
only *after* the creation of a separate type representation decision pass,
and this diff is already very big. The code for making the compiler understand
these items will be added later. The code for generating them will be added
later still, once the code for understanding them has been installed on
all our systems.
Since I was going to be working on the affected code anyway, this diff
also carries out two other decisions that came out of that discussion:
- the deletion of the ability to reserve a tag in a type for HAL,
either via a compiler option or via a pragma, and
- the deletion of the ability to represent a functor using the address
of a statically allocated object (which we haven't used and won't use,
because it slows down accesses to *all the other functors* of the type).
compiler/mercury_compile_front_end.m:
Invoke the new pass for making decisions about type representations
after the make_hlds pass. (We used to do only the final part of it then.)
Fix a bad dump stage name.
Add an extra check for what it means for a module to be error free.
Make a sub-switch explicit.
compiler/hlds.m:
compiler/make_hlds.m:
Move the modules that implement the new pass from the make_hlds package
to the hlds package, to give the compiler's top level access to them.
Make the same move for the modules that the new pass's modules need.
Since they are now part of hlds, they cannot reach into make_hlds,
and I think this is a cleaner solution than forwarding predicates.
Delete some forwarding predicates that are no longer needed.
compiler/notes/compiler_design.html:
Document the updated location of the moved modules.
Add an XXX to note a place where the documentation has not been
updated in the past.
compiler/du_type_layout.m:
Add code to implement the new pass.
Keep the algorithm for deciding type representations as close
to the previously used algorithm as possible, since this diff
is already big enough. (The previous algorithm was scattered across
add_type.m, add_foreign_enum.m, and make_hlds_passes.m.)
Simplifications and optimizations will come later, after this module
is merged with make_tags.m and with (at least) the foreign_enum half of
add_foreign_enum.m.
compiler/make_tags.m:
Keep the functionality of this module, which does both the first part
of deciding type representations (tentatively assigning tags to functors,
an assignment that may be overridden later), and the last part (packing
multiple adjacent less-than-word-sized enum args into a single word,
if possible.), but simplify it where possible, and note possibilities
for further improvements.
compiler/add_foreign_enum.m:
This module has two halves, one dealing with foreign_enum pragmas
and one dealing with foreign_export_enum pragmas.
Change the half that deals with foreign_enum pragmas to just build
a data structure that du_type_layout.m will need to make its decisions,
this structure being a map from type_ctors to the foreign enum
specification applicable to the current target language. Include
in this structure a component that add_foreign_enum.m itself can use
to report better error messages for duplicate foreign_enum pragmas;
this component records, for each type_ctor and language, the context
of the previous foreign_enum pragma for that combo.
Change the input for the half that deals with foreign_export_enum pragmas
to reflect the fact that it is invoked by du_type_layout.m after all
decisions about type representations have already been made.
compiler/add_special_pred.m:
Move this module from the make_hlds package to the hlds package,
since the code that adds special preds for type is now called from
du_type_layout.m.
Change the names of predicates to make clear whether they add
only the declaration of a predicate, only its definition, or both.
Don't try to pre-guess whether the implementation of a type's
compare predicate will need an index predicate. Let the code
that generates calls to the index predicate both declare and define
the index predicate. This change removes the potential for
inconsistencies between the two pieces of code.
compiler/add_pred.m:
Move this module from the make_hlds package to the hlds package,
since add_special_pred.m needs access to it.
compiler/add_type.m:
When adding a type definition to the HLDS, don't try to decide
its representation. Any such decision was tentative anyway, due
to the possibility of e.g. the later processing of foreign_type
or foreign_enum pragmas for the type. Likewise, don't try to
create the special (unify, compare) predicates for the type.
Leave both tasks to the du_type_layout pass.
Likewise, don't try to pack the representation of types, or record
no_tag types in the table of no_tag types, during the post-processing
pass either; leave both of these to du_type_layout as well.
Rename the predicate that post_processes type definitions to reflect
the two tasks left for it to do.
compiler/prog_data.m:
Do not store width information about the arguments of those data
constructors in the parse tree. That information is not computed
until later; until then, it was always filled in with dummy values.
(But see hlds_data.m below.)
Use bespoke types to represent the presence or absence of user-specified
unify and compare predicates.
Change the representation of data constructors to use a single "maybe"
type, not two lists, to denote the presence or absence of existentially
typed arguments.
Give the HLDS the ability to hold representation information about
abstract types that in the future we will get from type_repn items
in the defining modules' interface files.
Delete the uses_reserved_tag type, since we never use reserved tags
anymore.
compiler/prog_item.m:
Add the new type_repn item type, which is not used yet.
Delete the reserve_tag pragma.
Fix an earlier mistake in the wording of a context message.
compiler/hlds_data.m:
Put all the fields of hlds_du_type (the type definition variant dealing
with discriminated union types) that deal with type representation
issues in a single "maybe" field that is set to "no" before the
type representation decision pass has been run.
Add new type, constructor_repn, that stores the same information as the old
constructor type (defined in prog_data.m), PLUS the information
describing how terms with that data constructor are stored.
Likewise, add a new type ctor_arg_rep, which likewise stores
the widths of each constructor argument. When we implement
argument reordering, we would store the offset of the arg as well.
Since the parse tree representations of constructors and their arguments
don't store representation information anymore, the cons_table they
are stored in doesn't either. Make the lookup of representation information
for a given constructor possible by adding a map to the new "maybe" field
of hlds_du_type.
Provide some utility predicates.
Optimize some existing predicates.
Rename some types to better reflect their meaning.
compiler/hlds_module.m:
Provide a slot in the module_info for storing the information
gathered by make_hlds.m that is needed by the new pass.
compiler/make_hlds_separate_items.m:
When we see either a foreign_enum or a foreign_export_enum pragma,
return values of a bespoke type for them (a type defined in
hlds_module.m), instead of an item_pragma. This makes handling them
considerably easier.
compiler/make_hlds_passes.m:
With the changes in this diff, adding a type to the HLDS won't
decide its representation. Therefore delete the code that used
to loop over foreign_export_enum pragmas; in the absence of
the final type representation information, it won't work right.
Record the information that the du_type_layout pass will need
in the module_info.
compiler/add_pragma.m:
Delete the code for passing on foreign_enum and foreign_export_enum
pragmas to add_foreign_enum.m; they are now passed to add_foreign_enum.m
by du_type_layout.m.
Move a utility predicate to make_hlds_error.m, to allow add_foreign_enum.m
to call it.
compiler/make_hlds_error.m:
Add the utility predicate moved from add_pragma.m.
Move the module from the make_hlds to the hlds package.
compiler/module_qual.m:
Provide a mechanism for recording error messages about e.g. undefined
types without recording that we found an undefined type. This sounds
strange, but there is a valid use case.
When a type definition declares a functor's argument to be of an
undefined type, that error is usually fatal; we stop the compiler
from proceeding even to typechecking, since the typechecker will
probably abort with a map lookup failure. Most other references
to undefined types are similarly fatal for the same reason. However,
if e.g. a foreign_export_enum pragma refers to an undefined type,
that error *won't* be visible to the typechecker, and therefore
won't crash it. The error will still cause the compiler to exit
without generating any target language code, but at least it will be
able to run the typechecker and other semantic analysis passes.
Without this change, the compiler will report only one error in
the ee_invalid.m test case; with it, it reports *every* error
in the test case expected output.
compiler/module_qual.qualify_items.m:
Use the capability describe above for undefined types in
foreign_export_enum pragmas.
compiler/module_qual.qual_errors.m:
Delete a (somewhat incorrect) copy of a predicate in prog_item.m,
to reduce code duplication.
compiler/prog_type.m:
Add ways to represent abstract types whose representations are nevertheless
known (from type_repn items in the defining modules' interface files)
to be notag or dummy types. This will be needed to fix Mantis bug #441,
a fix that will probably be one of the first later changes to build
on this diff.
Delete a type moved to type_util.m.
compiler/type_util.m:
Provide extra versions of some predicates, with the difference between
the old and the new versions being that one requires type representations
to have been decided already, and the other one does not.
Move the definition of the ctor_defn type here from prog_type.m,
since prog_type.m itself does not use it, but type_util.m does.
Give some predicates more meaningful names.
compiler/parse_type_defn.m:
Simplify the code for parsing type definitions, to make it easier
to reuse to parse type_repn items.
Add a sanity check that requires existential constraints to have
*some* existential variables to apply to.
Allow "type_is_representable_in_n_bits" as a synonym for
"type_is_abstract_enum", since in the future we want to be able to pack
e.g. multiple int8s, not just multiple enums, into a single word.
Generate more specific error messages for some classes of malformed input.
compiler/parse_type_repn.m:
New module to parse type_repn items.
compiler/polymorphism.m:
Make some predicates that operate on type constructors take
the type constructors themselves as input arguments, not a whole type
*using* that type constructor. Put the arguments of those predicates
in a more standard order.
Note that some predicates don't belong in this module.
compiler/special_pred.m:
Make the code that decides whether a special predicate for a type
constructor can be defined lazily avoid using type representation
information. (Actually, we now make decisions about lazy vs eager
definitions after type representation is available, but that was
not so in an earlier version of this change, and the new code
is more robust.)
compiler/unify_proc.m:
When we decide to generate code for a compare predicate that needs
the type to have an index predicate, don't presume that the index
predicate has already been declared and defined; instead, declare
and define it then and there. (Index predicates are *never* called
from anywhere else.)
Pack the information needed to define a special predicate
into a single structure, to simplify the above.
Since the creation of a clause for a compare predicate may now require
the declaration and definition of an index predicate, the module_info
field of the unify_proc_info is now a writeable field.
Give some predicates and function symbols more meaningful names.
Note some problems with the existing code.
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_mode.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_solver.m:
compiler/check_typeclass.m:
compiler/code_info.m:
compiler/comp_unit_interface.m:
compiler/ctgc.selector.m:
compiler/ctgc.util.m:
compiler/default_func_mode.m:
compiler/det_report.m:
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/erl_code_gen.m:
compiler/export.m:
compiler/foreign.m:
compiler/get_dependencies.m:
compiler/goal_expr_to_goal.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_out_module.m:
compiler/inst_check.m:
compiler/inst_test.m:
compiler/inst_util.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_warn.m:
compiler/ml_accurate_gc.m:
compiler/ml_simplify_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mode_util.m:
compiler/modecheck_goal.m:
compiler/module_qual.collect_mq_info.m:
compiler/modules.m:
compiler/parse_item.m:
compiler/parse_pragma.m:
compiler/parse_tree.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
compiler/post_term_analysis.m:
compiler/proc_requests.m:
compiler/prog_item_stats.m:
compiler/qual_info.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/resolve_unify_functor.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/simplify_goal_ite.m:
compiler/stack_opt.m:
compiler/state_var.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/superhomogeneous.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/term_constr_build.m:
compiler/term_norm.m:
compiler/trailing_analysis.m:
compiler/type_constraints.m:
compiler/type_ctor_info.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/untupling.m:
compiler/unused_imports.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
Conform to the changes above.
tests/invalid/Mmakefile:
Disable the reserve_tag test case, as it is not applicable anymore.
tests/invalid/exported_foreign_enum.{m,err_exp}:
tests/invalid/pragma_qual_error.{m,err_exp}:
Delete reserve_tag pragmas from these test cases, and its effects
from the expected outputs.
tests/invalid/bad_foreign_type.err_exp:
tests/invalid/bigtest.err_exp:
tests/invalid/foreign_enum_invalid.err_exp:
tests/invalid/type_lhs_var.err_exp:
tests/invalid/uu_type.err_exp:
tests/invalid/where_abstract_enum.err_exp:
tests/invalid/where_direct_arg.err_exp:
Expect the updated messages for some errors.
tests/valid/Mmake.valid.common:
tests/valid/Mmakefile:
Disable any reserve_tag test cases, as they are not applicable anymore.
776 lines
33 KiB
Mathematica
776 lines
33 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1996-2012 The University of Melbourne.
|
|
% Copyright (C) 2015 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: module_qual.m.
|
|
% Main authors: stayl, fjh.
|
|
%
|
|
% The code in this module performs two tasks.
|
|
%
|
|
% - It checks for undefined types, typeclasses, insts and modes.
|
|
%
|
|
% - It module qualifies types, typeclasses, insts and modes within declaration
|
|
% items in the source code of the compilation unit. The heads of all
|
|
% declarations should be module qualified as they are read in by the parser;
|
|
% this module qualifies the bodies of those declarations.
|
|
%
|
|
% Note that we don't qualify the parts of the augmented compilation unit
|
|
% that derive from other modules' interface or optimization files, since
|
|
% those parts should be read in fully module qualified already.
|
|
%
|
|
% The algorithm we use does two passes over all the items in the compilation
|
|
% unit. The first pass records the set of modules, types, typeclasses, insts
|
|
% and modes that are visible in the compilation unit. The second uses this
|
|
% information to actually do this module's job.
|
|
%
|
|
% If any type, typeclass, inst or mode used in the module is not uniquely
|
|
% module qualifiable, i.e. if we either find zero matches for it, or we find
|
|
% two or more matches for it, we can generate an error message for it.
|
|
% We do so when we are module qualifying a compilation unit; we don't when
|
|
% we are qualifying the contents of an interface file.
|
|
%
|
|
% If the --warn-interface-imports option is set, we generate warnings about
|
|
% modules imported in the interface that are not used in the interface.
|
|
%
|
|
% Note that this module is NOT the only place in the compiler that does module
|
|
% qualification. The modes of lambda expressions are qualified in modes.m,
|
|
% and predicate and function names are qualified during typecheck, with
|
|
% the results recorded during the post_typecheck phase of the purity pass.
|
|
% This is because figuring out whether e.g. a call to predicate `p' calls
|
|
% module m1's predicate p or module m2's predicate p may require knowing
|
|
% the types of the arguments in the call.
|
|
%
|
|
% Since this module does not and cannot know about the module qualification
|
|
% of predicate names, function names and function symbols, it cannot figure out
|
|
% which modules are referred to in goals. The only goals that may appear
|
|
% in the interface section of a module are in promise declarations.
|
|
% If a promise goal contains any unqualified symbols, the second pass
|
|
% leaves the symbol unchanged, but since the eventual actual qualification
|
|
% of the symbol could refer to any of the modules imported in the interface,
|
|
% we consider them *all* of them to be "used".
|
|
%
|
|
% For the same reason (we don't know what modules predicate names,
|
|
% function names and function symbols in goals may refer to), this module
|
|
% cannot implement any equivalent of --warn-interface-imports that would
|
|
% report unnecessary imports in the *implementation* section of a module.
|
|
%
|
|
% If the --warn-unused-imports option is set, then unused_imports.m
|
|
% can generate all the warnings we would, but it can generate *better*
|
|
% messages, since unlike the code here, it can report that an imported module
|
|
% is unused *anywhere* in the module. However, even if --warn-unused-imports
|
|
% *is* set, the code in unused_imports.m won't be invoked if we stop
|
|
% compilation before its normal invocation time, due to e.g. type or more
|
|
% errors. What we should do is generate warnings here; print them if we
|
|
% stop before the unused_imports pass; throw them away if we *do* get to
|
|
% that pass. We don't (yet) do this.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.module_qual.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.error_util.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_data_event.
|
|
:- import_module parse_tree.prog_item.
|
|
:- import_module recompilation.
|
|
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type maybe_found_undef_type
|
|
---> did_not_find_undef_type
|
|
; found_undef_type.
|
|
|
|
:- type maybe_found_undef_inst
|
|
---> did_not_find_undef_inst
|
|
; found_undef_inst.
|
|
|
|
:- type maybe_found_undef_mode
|
|
---> did_not_find_undef_mode
|
|
; found_undef_mode.
|
|
|
|
:- type maybe_found_undef_typeclass
|
|
---> did_not_find_undef_typeclass
|
|
; found_undef_typeclass.
|
|
|
|
% module_qualify_aug_comp_unit(Globals, AugCompUnit0, AugCompUnit,
|
|
% EventSpecMap0, EventSpecMap, MaybeContext, EventSpecFileName, MQ_Info,
|
|
% UndefTypes, UndefInsts, UndefModes, UndefTypeClasses, !Specs):
|
|
%
|
|
% AugCompUnit is AugCompUnit0 with all items module qualified
|
|
% as much as possible; likewise for EventSpecMap0 and EventSpecMap.
|
|
%
|
|
% Errors in EventSpecMap0 will be reported as being for EventSpecFileName.
|
|
%
|
|
:- pred module_qualify_aug_comp_unit(globals::in,
|
|
aug_compilation_unit::in, aug_compilation_unit::out,
|
|
event_spec_map::in, event_spec_map::out, string::in, mq_info::out,
|
|
maybe_found_undef_type::out, maybe_found_undef_inst::out,
|
|
maybe_found_undef_mode::out, maybe_found_undef_typeclass::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
% module_qualify_parse_tree_int(Globals, ParseTreeInt0, ParseTreeInt,
|
|
% !Specs):
|
|
%
|
|
% ParseTreeInt is ParseTreeInt0 with all items module qualified
|
|
% as much as possible.
|
|
%
|
|
:- pred module_qualify_parse_tree_int(globals::in,
|
|
parse_tree_int::in, parse_tree_int::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% When we process types, typeclasses, insts or modes, we need to know
|
|
% whether they occur in the interface of the current module. This is
|
|
% so that if we see e.g. m1.t1 in the interface, we can mark module m1
|
|
% as being used in the interface, so we can avoid generating a warning
|
|
% about m1 being unused in the interface.
|
|
%
|
|
:- type mq_in_interface
|
|
---> mq_not_used_in_interface
|
|
; mq_used_in_interface.
|
|
|
|
% This is called from make_hlds to qualify the mode of an argument
|
|
% of a lambda expression.
|
|
%
|
|
:- pred qualify_lambda_mode(mq_in_interface::in, prog_context::in,
|
|
mer_mode::in, mer_mode::out, mq_info::in, mq_info::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
% This is called from make_hlds.m to qualify the modes in a
|
|
% clause mode annotation.
|
|
%
|
|
:- pred qualify_clause_mode_list(mq_in_interface::in, prog_context::in,
|
|
list(mer_mode)::in, list(mer_mode)::out, mq_info::in, mq_info::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
% This is called from make_hlds to qualify an explicit type qualification.
|
|
%
|
|
:- pred qualify_type_qualification(mq_in_interface::in, prog_context::in,
|
|
mer_type::in, mer_type::out, mq_info::in, mq_info::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
% The type mq_info holds information needed for doing module qualification.
|
|
%
|
|
:- type mq_info.
|
|
|
|
:- pred mq_info_get_found_undef_type(mq_info::in,
|
|
maybe_found_undef_type::out) is det.
|
|
:- pred mq_info_get_found_undef_inst(mq_info::in,
|
|
maybe_found_undef_inst::out) is det.
|
|
:- pred mq_info_get_found_undef_mode(mq_info::in,
|
|
maybe_found_undef_mode::out) is det.
|
|
:- pred mq_info_get_found_undef_typeclass(mq_info::in,
|
|
maybe_found_undef_typeclass::out) is det.
|
|
|
|
:- type maybe_suppress_found_undef
|
|
---> do_not_suppress_found_undef
|
|
; suppress_found_undef.
|
|
|
|
:- pred mq_info_get_suppress_found_undef(mq_info::in,
|
|
maybe_suppress_found_undef::out) is det.
|
|
:- pred mq_info_set_suppress_found_undef(maybe_suppress_found_undef::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
|
|
:- pred mq_info_get_recompilation_info(mq_info::in,
|
|
maybe(recompilation_info)::out) is det.
|
|
:- pred mq_info_set_recompilation_info(maybe(recompilation_info)::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
|
|
% The type partial_qualifier_info holds info need for computing which
|
|
% partial quantifiers are visible -- see get_partial_qualifiers/3.
|
|
%
|
|
:- type partial_qualifier_info.
|
|
|
|
:- pred mq_info_get_partial_qualifier_info(mq_info::in,
|
|
partial_qualifier_info::out) is det.
|
|
|
|
% Suppose we are processing a definition which defines the symbol
|
|
% foo.bar.baz.quux/1. Then we insert the following symbols
|
|
% into the symbol table:
|
|
% - if the current value of the NeedQual flag at this point
|
|
% is `may_be_unqualified',
|
|
% i.e. module `foo.bar.baz' was imported,
|
|
% then we insert the fully unqualified symbol quux/1;
|
|
% - if module `foo.bar.baz' occurs in the "imported" section,
|
|
% i.e. if module `foo.bar' was imported,
|
|
% then we insert the partially qualified symbol baz.quux/1;
|
|
% - if module `foo.bar' occurs in the "imported" section,
|
|
% i.e. if module `foo' was imported,
|
|
% then we insert the partially qualified symbol bar.baz.quux/1;
|
|
% - we always insert the fully qualified symbol foo.bar.baz.quux/1.
|
|
%
|
|
% The predicate `get_partial_qualifiers' returns all of the
|
|
% partial qualifiers for which we need to insert definitions,
|
|
% i.e. all the ones which are visible. For example,
|
|
% given as input `foo.bar.baz', it returns a list containing
|
|
% (1) `baz', iff `foo.bar' is imported, and
|
|
% (2) `bar.baz', iff `foo' is imported.
|
|
% Note that the caller will still need to handle the fully-qualified
|
|
% and fully-unqualified versions separately.
|
|
%
|
|
:- pred get_partial_qualifiers(mq_in_interface::in, module_name::in,
|
|
partial_qualifier_info::in, list(module_name)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- include_module parse_tree.module_qual.collect_mq_info.
|
|
:- include_module parse_tree.module_qual.id_set.
|
|
:- include_module parse_tree.module_qual.qual_errors.
|
|
:- include_module parse_tree.module_qual.qualify_items.
|
|
|
|
:- import_module libs.options.
|
|
:- import_module parse_tree.get_dependencies.
|
|
:- import_module parse_tree.module_qual.collect_mq_info.
|
|
:- import_module parse_tree.module_qual.id_set.
|
|
:- import_module parse_tree.module_qual.qual_errors.
|
|
:- import_module parse_tree.module_qual.qualify_items.
|
|
|
|
:- import_module bool.
|
|
:- import_module map.
|
|
:- import_module multi_map.
|
|
:- import_module pair.
|
|
:- import_module set.
|
|
:- import_module term.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
module_qualify_aug_comp_unit(Globals, AugCompUnit0, AugCompUnit,
|
|
EventSpecMap0, EventSpecMap, EventSpecFileName, !:Info,
|
|
UndefTypes, UndefInsts, UndefModes, UndefTypeClasses, !Specs) :-
|
|
AugCompUnit0 = aug_compilation_unit(ModuleName, ModuleNameContext,
|
|
ModuleVersionNumbers, SrcItemBlocks0,
|
|
DirectIntItemBlocks, IndirectIntItemBlocks,
|
|
OptItemBlocks, IntForOptItemBlocks),
|
|
init_mq_info(Globals, ModuleName, SrcItemBlocks0,
|
|
DirectIntItemBlocks ++ IndirectIntItemBlocks,
|
|
OptItemBlocks, IntForOptItemBlocks, should_report_errors, !:Info),
|
|
collect_mq_info_in_item_blocks(src_section_mq_info, SrcItemBlocks0,
|
|
!Info),
|
|
collect_mq_info_in_item_blocks(int_section_mq_info, DirectIntItemBlocks,
|
|
!Info),
|
|
% XXX ITEM_LIST asymmetry: collect from 2, qualify 1
|
|
module_qualify_items_in_src_item_blocks(SrcItemBlocks0, SrcItemBlocks,
|
|
!Info, !Specs),
|
|
AugCompUnit = aug_compilation_unit(ModuleName, ModuleNameContext,
|
|
ModuleVersionNumbers, SrcItemBlocks,
|
|
DirectIntItemBlocks, IndirectIntItemBlocks,
|
|
OptItemBlocks, IntForOptItemBlocks),
|
|
|
|
map.to_assoc_list(EventSpecMap0, EventSpecList0),
|
|
qualify_event_specs(mq_not_used_in_interface, EventSpecFileName,
|
|
EventSpecList0, EventSpecList, !Info, !Specs),
|
|
map.from_assoc_list(EventSpecList, EventSpecMap),
|
|
mq_info_get_found_undef_type(!.Info, UndefTypes),
|
|
mq_info_get_found_undef_inst(!.Info, UndefInsts),
|
|
mq_info_get_found_undef_mode(!.Info, UndefModes),
|
|
mq_info_get_found_undef_typeclass(!.Info, UndefTypeClasses),
|
|
|
|
% Warn about any unused module imports in the interface.
|
|
% There is a special case involving type class instances that
|
|
% we need to handle here. Consider:
|
|
%
|
|
% :- module foo.
|
|
% :- interface.
|
|
%
|
|
% :- import_module bar.
|
|
% :- typeclass tc1(T) <= tc2(T).
|
|
% :- instance tc1(unit).
|
|
%
|
|
% where module bar exports the instance tc2(unit). We must import
|
|
% the module bar in the interface of the module foo in order for
|
|
% the superclass constraint on the instance tc1(unit) to be satisfied.
|
|
% However, at this stage of compilation we do not know that the
|
|
% instance tc2(unit) needs to be visible. (Knowing this would require
|
|
% a more extensive analysis of type classes and instances to be done
|
|
% in this module.)
|
|
%
|
|
% In order to prevent the import of the module bar being erroneously
|
|
% reported as unused, we make the conservative assumption that any
|
|
% imported module that exports a type class instance is used in
|
|
% the interface of the importing module, except if the importing
|
|
% module itself exports _no_ type class instances.
|
|
mq_info_get_as_yet_unused_interface_modules(!.Info, UnusedImportsMap0),
|
|
mq_info_get_exported_instances_flag(!.Info, ModuleExportsInstances),
|
|
(
|
|
ModuleExportsInstances = yes,
|
|
mq_info_get_imported_instance_modules(!.Info, InstanceImports),
|
|
map.delete_list(set.to_sorted_list(InstanceImports),
|
|
UnusedImportsMap0, UnusedImportsMap)
|
|
;
|
|
ModuleExportsInstances = no,
|
|
UnusedImportsMap = UnusedImportsMap0
|
|
),
|
|
( if
|
|
not map.is_empty(UnusedImportsMap),
|
|
globals.lookup_bool_option(Globals, warn_interface_imports, yes)
|
|
then
|
|
map.to_assoc_list(UnusedImportsMap, UnusedImports),
|
|
list.foldl(warn_unused_interface_import(ModuleName), UnusedImports,
|
|
!Specs)
|
|
else
|
|
true
|
|
).
|
|
|
|
module_qualify_parse_tree_int(Globals, ParseTreeInt0, ParseTreeInt, !Specs) :-
|
|
ParseTreeInt0 = parse_tree_int(ModuleName, IntFileKind, ModuleNameContext,
|
|
MaybeVersionNumbers, IntIncls, ImpIncls, IntAvails, ImpAvails,
|
|
IntItems0, ImpItems0),
|
|
IntSrcItemBlocks0 = [item_block(sms_interface, term.context_init,
|
|
IntIncls, IntAvails, IntItems0)],
|
|
ImpSrcItemBlocks0 = [item_block(sms_implementation, term.context_init,
|
|
ImpIncls, ImpAvails, ImpItems0)],
|
|
% XXX ITEM_LIST The completely separate treatment of the interface
|
|
% and implementation part of an interface file preserves old behavior;
|
|
% write_short_interface_file in write_module_interface_files.m used
|
|
% to call module_qualify_items separately on the interface and
|
|
% implementation items. I (zs) this is likely to be a bug, in that
|
|
% the module qualification of the items in the implementation section
|
|
% doesn't see the declarations in the interface section.
|
|
% XXX ITEM_LIST Check whether we can get a nonempty list of implicit
|
|
% dependencies in either call to collect_mq_info_in_aug_item_blocks below.
|
|
DummyItemBlocks = []:list(src_item_block),
|
|
some [!IntInfo] (
|
|
init_mq_info(Globals, ModuleName, IntSrcItemBlocks0,
|
|
DummyItemBlocks, DummyItemBlocks, DummyItemBlocks,
|
|
should_not_report_errors, !:IntInfo),
|
|
collect_mq_info_in_item_blocks(src_section_mq_info, IntSrcItemBlocks0,
|
|
!IntInfo),
|
|
module_qualify_items_loop(mq_used_in_interface,
|
|
IntItems0, IntItems, !.IntInfo, _, !Specs)
|
|
),
|
|
some [!ImpInfo] (
|
|
init_mq_info(Globals, ModuleName, ImpSrcItemBlocks0,
|
|
DummyItemBlocks, DummyItemBlocks, DummyItemBlocks,
|
|
should_not_report_errors, !:ImpInfo),
|
|
collect_mq_info_in_item_blocks(src_section_mq_info, ImpSrcItemBlocks0,
|
|
!ImpInfo),
|
|
module_qualify_items_loop(mq_not_used_in_interface,
|
|
ImpItems0, ImpItems, !.ImpInfo, _, !Specs)
|
|
),
|
|
ParseTreeInt = parse_tree_int(ModuleName, IntFileKind, ModuleNameContext,
|
|
MaybeVersionNumbers, IntIncls, ImpIncls, IntAvails, ImpAvails,
|
|
IntItems, ImpItems).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
qualify_lambda_mode(InInt, Context, Mode0, Mode, !Info, !Specs) :-
|
|
ErrorContext = mqec_lambda_expr(Context),
|
|
qualify_mode(InInt, ErrorContext, Mode0, Mode, !Info, !Specs).
|
|
|
|
qualify_clause_mode_list(InInt, Context, Modes0, Modes, !Info, !Specs) :-
|
|
ErrorContext = mqec_clause_mode_annotation(Context),
|
|
qualify_mode_list(InInt, ErrorContext, Modes0, Modes, !Info, !Specs).
|
|
|
|
qualify_type_qualification(InInt, Context, Type0, Type, !Info, !Specs) :-
|
|
ErrorContext = mqec_type_qual(Context),
|
|
qualify_type(InInt, ErrorContext, Type0, Type, !Info, !Specs).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type partial_qualifier_info
|
|
---> partial_qualifier_info(module_id_set).
|
|
|
|
mq_info_get_partial_qualifier_info(MQInfo, QualifierInfo) :-
|
|
mq_info_get_modules(MQInfo, ModuleIdSet),
|
|
QualifierInfo = partial_qualifier_info(ModuleIdSet).
|
|
|
|
get_partial_qualifiers(InInt, ModuleName, PartialQualInfo,
|
|
PartialQualifiers) :-
|
|
PartialQualInfo = partial_qualifier_info(ModuleIdSet),
|
|
(
|
|
ModuleName = unqualified(_),
|
|
PartialQualifiers = []
|
|
;
|
|
ModuleName = qualified(Parent, Child),
|
|
get_partial_qualifiers_acc(InInt, Parent, unqualified(Child),
|
|
ModuleIdSet, [], PartialQualifiers)
|
|
).
|
|
|
|
:- pred get_partial_qualifiers_acc(mq_in_interface::in,
|
|
module_name::in, module_name::in, module_id_set::in,
|
|
list(module_name)::in, list(module_name)::out) is det.
|
|
|
|
get_partial_qualifiers_acc(InInt, ImplicitPart, ExplicitPart, ModuleIdSet,
|
|
!Qualifiers) :-
|
|
% If the ImplicitPart module was imported, rather than just being used,
|
|
% then insert the ExplicitPart module into the list of valid partial
|
|
% qualifiers.
|
|
( if
|
|
parent_module_is_imported(InInt, ImplicitPart,
|
|
ExplicitPart, ModuleIdSet)
|
|
then
|
|
!:Qualifiers = [ExplicitPart | !.Qualifiers]
|
|
else
|
|
true
|
|
),
|
|
% Recursively try to add the other possible partial qualifiers.
|
|
(
|
|
ImplicitPart = qualified(Parent, Child),
|
|
NextImplicitPart = Parent,
|
|
NextExplicitPart = add_outermost_qualifier(Child, ExplicitPart),
|
|
get_partial_qualifiers_acc(InInt, NextImplicitPart, NextExplicitPart,
|
|
ModuleIdSet, !Qualifiers)
|
|
;
|
|
ImplicitPart = unqualified(_)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Utility predicates.
|
|
%
|
|
|
|
:- pred update_recompilation_info(
|
|
pred(recompilation_info, recompilation_info)::in(pred(in, out) is det),
|
|
mq_info::in, mq_info::out) is det.
|
|
|
|
update_recompilation_info(Pred, !Info) :-
|
|
mq_info_get_recompilation_info(!.Info, MaybeRecompInfo0),
|
|
(
|
|
MaybeRecompInfo0 = yes(RecompInfo0),
|
|
Pred(RecompInfo0, RecompInfo),
|
|
mq_info_set_recompilation_info(yes(RecompInfo), !Info)
|
|
;
|
|
MaybeRecompInfo0 = no
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
% If the current item is in the interface, remove its module name from
|
|
% the list of modules not used in the interface, and if the module name
|
|
% is itself module-qualified, mark its ancestor modules as used as well.
|
|
%
|
|
:- pred mq_info_set_module_used(mq_in_interface::in, module_name::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
|
|
mq_info_set_module_used(InInt, ModuleName, !Info) :-
|
|
(
|
|
InInt = mq_used_in_interface,
|
|
mq_info_get_as_yet_unused_interface_modules(!.Info, AsYetUnused0),
|
|
( if map.remove(ModuleName, _, AsYetUnused0, AsYetUnused) then
|
|
mq_info_set_as_yet_unused_interface_modules(AsYetUnused, !Info)
|
|
else
|
|
% ModuleName was not in AsYetUnused0.
|
|
true
|
|
),
|
|
(
|
|
ModuleName = qualified(ParentModule, _),
|
|
mq_info_set_module_used(InInt, ParentModule, !Info)
|
|
;
|
|
ModuleName = unqualified(_)
|
|
)
|
|
;
|
|
InInt = mq_not_used_in_interface
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Access and initialisation predicates.
|
|
%
|
|
|
|
:- type maybe_should_report_errors
|
|
---> should_not_report_errors
|
|
; should_report_errors.
|
|
|
|
% We process only the interface, so we will warn only about unused
|
|
% imports in parent's INTERFACE sections.
|
|
:- type maybe_warn_unused_imports_in_parents
|
|
---> should_not_warn_unused_imports_in_parents
|
|
; should_warn_unused_imports_in_parents.
|
|
|
|
:- type mq_sub_info
|
|
---> mq_sub_info(
|
|
% The name of the current module.
|
|
mqsi_this_module :: module_name,
|
|
|
|
% Modules which have been imported or used, i.e. the ones
|
|
% for which there was a `:- import_module' or `:- use_module'
|
|
% declaration in this module.
|
|
mqsi_imported_modules :: set(module_name),
|
|
|
|
% Modules from which `:- instance' declarations have
|
|
% been imported.
|
|
mqsi_imported_instance_modules :: set(module_name),
|
|
|
|
% Does this module export any type class instances?
|
|
mqsi_exported_instances_flag :: bool,
|
|
|
|
% Are there any undefined types, insts, modes or typeclasses?
|
|
mqsi_found_undef_type :: maybe_found_undef_type,
|
|
mqsi_found_undef_inst :: maybe_found_undef_inst,
|
|
mqsi_found_undef_mode :: maybe_found_undef_mode,
|
|
mqsi_found_undef_typeclass :: maybe_found_undef_typeclass,
|
|
|
|
% Do we want to suppress the recording of an undef type, inst,
|
|
% mode or typeclass, as such? We sometimes do, when the error
|
|
% won't prevent us from continuing on to later compiler passes.
|
|
% (We still generate error messages in such instances, of
|
|
% course.)
|
|
mqsi_suppress_found_undef :: maybe_suppress_found_undef,
|
|
|
|
% Do we want to report errors.
|
|
mqsi_should_report_errors :: maybe_should_report_errors,
|
|
mqsi_warn_parents_imports ::
|
|
maybe_warn_unused_imports_in_parents,
|
|
|
|
% The number of errors found.
|
|
mqsi_num_errors :: int
|
|
).
|
|
|
|
:- type mq_info
|
|
---> mq_info(
|
|
% Keep the size of the main mq_info structure at eight fields,
|
|
% as this allows Boehm gc to allocate memory blocks that don't
|
|
% have wasted unused space.
|
|
mqi_sub_info :: mq_sub_info,
|
|
|
|
% Sets of all modules, types, insts, modes, and typeclasses
|
|
% visible in this module.
|
|
mqi_modules :: module_id_set,
|
|
mqi_types :: type_id_set,
|
|
mqi_insts :: inst_id_set,
|
|
mqi_modes :: mode_id_set,
|
|
mqi_classes :: class_id_set,
|
|
|
|
% Map each modules known to be imported in the interface
|
|
% that is not yet known to be needed in the interface
|
|
% to the location (or sometimes, locations) of the import.
|
|
mqi_as_yet_unused_interface_modules :: map(module_name,
|
|
one_or_more(prog_context)),
|
|
|
|
mqi_maybe_recompilation_info :: maybe(recompilation_info)
|
|
).
|
|
|
|
:- pred init_mq_info(globals::in, module_name::in,
|
|
list(item_block(MS1))::in,
|
|
list(item_block(MS2))::in,
|
|
list(item_block(MS3))::in,
|
|
list(item_block(MS4))::in,
|
|
maybe_should_report_errors::in, mq_info::out) is det.
|
|
|
|
init_mq_info(Globals, ModuleName, ItemBlocksA, ItemBlocksB, ItemBlocksC,
|
|
ItemBlocksD, ReportErrors, Info) :-
|
|
get_implicit_dependencies_in_item_blocks(Globals, ItemBlocksA,
|
|
ImportDepsA, UseDepsA),
|
|
get_implicit_dependencies_in_item_blocks(Globals, ItemBlocksB,
|
|
ImportDepsB, UseDepsB),
|
|
get_implicit_dependencies_in_item_blocks(Globals, ItemBlocksC,
|
|
ImportDepsC, UseDepsC),
|
|
get_implicit_dependencies_in_item_blocks(Globals, ItemBlocksD,
|
|
ImportDepsD, UseDepsD),
|
|
ImportedModules = set.union_list([
|
|
set.sorted_list_to_set(multi_map.keys(ImportDepsA)),
|
|
set.sorted_list_to_set(multi_map.keys(ImportDepsB)),
|
|
set.sorted_list_to_set(multi_map.keys(ImportDepsC)),
|
|
set.sorted_list_to_set(multi_map.keys(ImportDepsD)),
|
|
set.sorted_list_to_set(multi_map.keys(UseDepsA)),
|
|
set.sorted_list_to_set(multi_map.keys(UseDepsB)),
|
|
set.sorted_list_to_set(multi_map.keys(UseDepsC)),
|
|
set.sorted_list_to_set(multi_map.keys(UseDepsD))
|
|
]),
|
|
set.init(InstanceModules),
|
|
ExportedInstancesFlag = no,
|
|
globals.lookup_bool_option(Globals, warn_interface_imports_in_parents,
|
|
WarnInterfaceImportsInParents),
|
|
% All the warnings generated by module_qual.*m for unused modules
|
|
% are for modules imported in the interface; see the comment at the
|
|
% top of this module.
|
|
(
|
|
WarnInterfaceImportsInParents = no,
|
|
WarnUnusedImportsInParents = should_not_warn_unused_imports_in_parents
|
|
;
|
|
WarnInterfaceImportsInParents = yes,
|
|
WarnUnusedImportsInParents = should_warn_unused_imports_in_parents
|
|
),
|
|
SubInfo = mq_sub_info(ModuleName, ImportedModules, InstanceModules,
|
|
ExportedInstancesFlag,
|
|
did_not_find_undef_type, did_not_find_undef_inst,
|
|
did_not_find_undef_mode, did_not_find_undef_typeclass,
|
|
do_not_suppress_found_undef,
|
|
ReportErrors, WarnUnusedImportsInParents, 0),
|
|
|
|
id_set_init(ModuleIdSet),
|
|
id_set_init(TypeIdSet),
|
|
id_set_init(InstIdSet),
|
|
id_set_init(ModeIdSet),
|
|
id_set_init(ClassIdSet),
|
|
map.init(AsYetUnusedInterfaceModules),
|
|
globals.lookup_bool_option(Globals, smart_recompilation,
|
|
SmartRecompilation),
|
|
(
|
|
SmartRecompilation = no,
|
|
MaybeRecompInfo = no
|
|
;
|
|
SmartRecompilation = yes,
|
|
MaybeRecompInfo = yes(init_recompilation_info(ModuleName))
|
|
),
|
|
Info = mq_info(SubInfo, ModuleIdSet,
|
|
TypeIdSet, InstIdSet, ModeIdSet, ClassIdSet,
|
|
AsYetUnusedInterfaceModules, MaybeRecompInfo).
|
|
|
|
:- pred mq_info_get_modules(mq_info::in, module_id_set::out) is det.
|
|
:- pred mq_info_get_types(mq_info::in, type_id_set::out) is det.
|
|
:- pred mq_info_get_insts(mq_info::in, inst_id_set::out) is det.
|
|
:- pred mq_info_get_modes(mq_info::in, mode_id_set::out) is det.
|
|
:- pred mq_info_get_classes(mq_info::in, class_id_set::out) is det.
|
|
:- pred mq_info_get_as_yet_unused_interface_modules(mq_info::in,
|
|
map(module_name, one_or_more(prog_context))::out) is det.
|
|
% mq_info_get_recompilation_info is exported
|
|
|
|
:- pred mq_info_get_this_module(mq_info::in, module_name::out) is det.
|
|
:- pred mq_info_get_imported_modules(mq_info::in, set(module_name)::out)
|
|
is det.
|
|
:- pred mq_info_get_imported_instance_modules(mq_info::in,
|
|
set(module_name)::out) is det.
|
|
:- pred mq_info_get_exported_instances_flag(mq_info::in, bool::out) is det.
|
|
% mq_info_get_type_error_flag is exported
|
|
% mq_info_get_mode_error_flag is exported
|
|
:- pred mq_info_get_should_report_errors(mq_info::in,
|
|
maybe_should_report_errors::out) is det.
|
|
:- pred mq_info_get_should_warn_unused_imports_in_parents(mq_info::in,
|
|
maybe_warn_unused_imports_in_parents::out) is det.
|
|
|
|
mq_info_get_modules(Info, X) :-
|
|
X = Info ^ mqi_modules.
|
|
mq_info_get_types(Info, X) :-
|
|
X = Info ^ mqi_types.
|
|
mq_info_get_insts(Info, X) :-
|
|
X = Info ^ mqi_insts.
|
|
mq_info_get_modes(Info, X) :-
|
|
X = Info ^ mqi_modes.
|
|
mq_info_get_classes(Info, X) :-
|
|
X = Info ^ mqi_classes.
|
|
mq_info_get_as_yet_unused_interface_modules(Info, X) :-
|
|
X = Info ^ mqi_as_yet_unused_interface_modules.
|
|
mq_info_get_recompilation_info(Info, X) :-
|
|
X = Info ^ mqi_maybe_recompilation_info.
|
|
|
|
mq_info_get_this_module(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_this_module.
|
|
mq_info_get_imported_modules(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_imported_modules.
|
|
mq_info_get_imported_instance_modules(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_imported_instance_modules.
|
|
mq_info_get_exported_instances_flag(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_exported_instances_flag.
|
|
mq_info_get_found_undef_type(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_found_undef_type.
|
|
mq_info_get_found_undef_inst(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_found_undef_inst.
|
|
mq_info_get_found_undef_mode(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_found_undef_mode.
|
|
mq_info_get_found_undef_typeclass(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_found_undef_typeclass.
|
|
mq_info_get_suppress_found_undef(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_suppress_found_undef.
|
|
mq_info_get_should_report_errors(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_should_report_errors.
|
|
mq_info_get_should_warn_unused_imports_in_parents(Info, X) :-
|
|
X = Info ^ mqi_sub_info ^ mqsi_warn_parents_imports.
|
|
|
|
:- pred mq_info_set_modules(module_id_set::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_types(type_id_set::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_insts(inst_id_set::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_modes(mode_id_set::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_classes(class_id_set::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_as_yet_unused_interface_modules(
|
|
map(module_name, one_or_more(prog_context))::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
% mq_info_get_recompilation_info is exported
|
|
|
|
:- pred mq_info_set_imported_instance_modules(set(module_name)::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_imported_modules(set(module_name)::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_exported_instances_flag(bool::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_found_undef_type(mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_found_undef_inst(mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_found_undef_mode(mq_info::in, mq_info::out) is det.
|
|
:- pred mq_info_set_found_undef_typeclass(mq_info::in, mq_info::out) is det.
|
|
|
|
mq_info_set_modules(X, !Info) :-
|
|
!Info ^ mqi_modules := X.
|
|
mq_info_set_types(X, !Info) :-
|
|
!Info ^ mqi_types := X.
|
|
mq_info_set_insts(X, !Info) :-
|
|
!Info ^ mqi_insts := X.
|
|
mq_info_set_modes(X, !Info) :-
|
|
!Info ^ mqi_modes := X.
|
|
mq_info_set_classes(X, !Info) :-
|
|
!Info ^ mqi_classes := X.
|
|
mq_info_set_as_yet_unused_interface_modules(X, !Info) :-
|
|
!Info ^ mqi_as_yet_unused_interface_modules := X.
|
|
mq_info_set_recompilation_info(X, !Info) :-
|
|
!Info ^ mqi_maybe_recompilation_info := X.
|
|
|
|
mq_info_set_imported_modules(X, !Info) :-
|
|
!Info ^ mqi_sub_info ^ mqsi_imported_modules := X.
|
|
mq_info_set_imported_instance_modules(X, !Info) :-
|
|
!Info ^ mqi_sub_info ^ mqsi_imported_instance_modules := X.
|
|
mq_info_set_exported_instances_flag(X, !Info) :-
|
|
!Info ^ mqi_sub_info ^ mqsi_exported_instances_flag := X.
|
|
mq_info_set_found_undef_type(!Info) :-
|
|
X = found_undef_type,
|
|
!Info ^ mqi_sub_info ^ mqsi_found_undef_type := X.
|
|
mq_info_set_found_undef_inst(!Info) :-
|
|
X = found_undef_inst,
|
|
!Info ^ mqi_sub_info ^ mqsi_found_undef_inst := X.
|
|
mq_info_set_found_undef_mode(!Info) :-
|
|
X = found_undef_mode,
|
|
!Info ^ mqi_sub_info ^ mqsi_found_undef_mode := X.
|
|
mq_info_set_found_undef_typeclass(!Info) :-
|
|
X = found_undef_typeclass,
|
|
!Info ^ mqi_sub_info ^ mqsi_found_undef_typeclass := X.
|
|
mq_info_set_suppress_found_undef(X, !Info) :-
|
|
!Info ^ mqi_sub_info ^ mqsi_suppress_found_undef := X.
|
|
|
|
:- pred mq_info_record_undef_mq_id(id_type::in,
|
|
mq_info::in, mq_info::out) is det.
|
|
|
|
mq_info_record_undef_mq_id(IdType, !Info) :-
|
|
mq_info_get_suppress_found_undef(!.Info, SuppressFoundUndef),
|
|
(
|
|
SuppressFoundUndef = suppress_found_undef
|
|
;
|
|
SuppressFoundUndef = do_not_suppress_found_undef,
|
|
(
|
|
IdType = type_id,
|
|
mq_info_set_found_undef_type(!Info)
|
|
;
|
|
IdType = inst_id,
|
|
mq_info_set_found_undef_inst(!Info)
|
|
;
|
|
IdType = mode_id,
|
|
mq_info_set_found_undef_mode(!Info)
|
|
;
|
|
IdType = class_id,
|
|
mq_info_set_found_undef_typeclass(!Info)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.module_qual.
|
|
%---------------------------------------------------------------------------%
|