compiler/module_qual.id_set.m:
As above. Also give the affected type a better name.
compiler/module_qual.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
Conform to the change above.
compiler/error_spec.m:
This new module contains the part of the old error_util.m that defines
the error_spec type, and some functions that can help construct pieces
of error_specs. Most modules of the compiler that deal with errors
will need to import only this part of the old error_util.m.
This change also renames the format_component type to format_piece,
which matches our long-standing naming convention for variables containing
(lists of) values of this type.
compiler/write_error_spec.m:
This new module contains the part of the old error_util.m that
writes out error specs, and converts them to strings.
This diff marks as obsolete the versions of predicates that
write out error specs to the current output stream, without
*explicitly* specifying the intended stream.
compiler/error_sort.m:
This new module contains the part of the old error_util.m that
sorts lists of error specs and error msgs.
compiler/error_type_util.m:
This new module contains the part of the old error_util.m that
convert types to format_pieces that generate readable output.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Include and document the new modules.
compiler/error_util.m:
The code remaining in the original error_util.m consists of
general utility predicates and functions that don't fit into
any of the modules above.
Delete an unneeded pair of I/O states from the argument list
of a predicate.
compiler/file_util.m:
Move the unable_to_open_file predicate here from error_util.m,
since it belongs here. Mark another predicate that writes
to the current output stream as obsolete.
compiler/hlds_error_util.m:
Mark two predicates that wrote out error_spec to the current output
stream as obsolete, and add versions that take an explicit output stream.
compiler/Mercury.options:
Compile the modules that call the newly obsoleted predicates
with --no-warn-obsolete, for the time being.
compiler/*.m:
Conform to the changes above, mostly by updating import_module
declarations, and renaming format_component to format_piece.
compiler/recompilation.m:
Add a distinguishing prefix to the names of both types relating to
recompilation items, and to the names of their function symbols,
in order to avoid confusion between them and the items defined in
prog_item.m.
Update the names of the related functions.
compiler/add_pragma_type_spec.m:
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/module_qual.id_set.m:
compiler/module_qual.qualify_items.m:
compiler/proc_requests.m:
compiler/prog_item.m:
compiler/qual_info.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.used_file.m:
compiler/recompilation.version.m:
Conform to the change above.
compiler/recompilation.m:
Introduce a new enum type, used_item_type, which has equivalents
of those item_types for which we collect used item sets. This allows us
to delete several calls to unexpected.
Rename type_abstract_item to type_name_item and type_body_item to
type_defn_item.
compiler/recompilation.used_file.m:
Tighten the definition of the resolved_functor type by changing the types
of some fields from generic (e.g. item_name) to specific (e.g. type_ctor).
Specify that the arity recorded for predicates and functions is
pred_form_arity, since that is what the code that actually resolves
references in the pred table uses, even though some other parts of
the code took it to be user arity, which is different for functions.
Mark one of these differences with XXXs, since they are likely to be bugs.
Fix another, since in that case it is *clear* that it was a bug.
Also give some of the function symbols clearer names, and put their
arguments in their conventional order.
compiler/prog_data.m:
Add a type for use in recompilation.used_file.m.
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/module_qual.id_set.m:
compiler/module_qual.qualify_items.m:
compiler/proc_requests.m:
compiler/qual_info.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
Conform to the changes above.
In some cases, give some predicates and/or variables more meaningful names,
or convert clause lists into explicit disjunctions. (In some cases,
the latter revealed arguments that all clauses ignored.)
The old code used item_id_sets for representing several closely related
but nevertheless significantly different pieces of information. These had
different invariants, but these could not be expressed in the type.
Using a different type for each purpose allows encoding the applicable
invariants in the types.
Also, the original code was organized around higher order code
that (a) used an item_type key to get a field from an item_id_set,
(b) did something with that field, and then, in some cases
(c) put its updated version back into the item_id_set.
It often did this in a loop over some, but not all, item_type values.
This diff replaces such code with code that (a) deconstructs a value
in one of item_id_set's replacement types, (b) uses a separate call
to process each field that needs to be processed, and then maybe
(c) constructs a new value containing the updated field.
This new approach has several advantages.
- It is more direct and hence more understandable. Due to the extra code
that used to be required by the higher order machinery, it can also be
shorter.
- It made clear that two of the fields of item_id_set, the fields
ostensibly containing information about mutables and foreign_procs,
were *never actually used*.
- It also works when the fields are not all the same type. The old code
stored information about instances separately from item_id_sets
precisely because it would have required a field of a different type.
- This last point allows a future diff to further specialize the types
of the fields. Some now store items; in the future, they could store
either just one specific kind of item, or one of a small set of kinds
of items; e.g. the fields for predicates and functions could store
one of item_pred_decl_infos, item_mode_decl_infos or item_decl_pragma_infos.
- It is also more efficient. Some of the old traversals allocated a new
item_id_set every time they updated a field, with their replacement
traversals never constructing a new item_id_set (or rather a value
of one of its replacement types) until the traversal is complete.
One minor aspect of the change is that this diff consistently puts insts
before modes in data structures and in the code that operates on them,
as we do in the rest of the compiler. Another is that it uses the name_arity
type to replace the type that the old code used, which was pair(string, int).
compiler/recompilation.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
As above.
Delete assignments to !:MaybeStoppingReason that assign it the value
("no") that !.MaybeStoppingReason already contains, as tested
immediately above.
Add XXX RECOMP where further changes are desirable.
compiler/module_qual.id_set.m:
Put insts before modes in id_type.
library/cord.m:
Add foldl versions with two and three accumulators.
NEWS:
Announce the new predicates.
tests/recompilation/two_module_debug:
Add this script, which can help debug problems with smart recompilation.
tests/recompilation/Mercury.options:
Fix indentation.
This fixes the second incarnation of Mantis bug #401. (The first incarnation
was the handling of such modules when generating target code.)
compiler/grab_modules.m:
Compute the set of modules that have a use_module declaration in the
interface section and an import_module declaration in the implementation
section, and set the status of the items imported from that module
accordingly.
compiler/module_qual.id_set.m:
If module A defines an entity (such as a type) that module B refers to
without the required qualification (which can happen if B has a use_module,
not import_module for A), then do NOT report A as unused in B; it IS used,
just not properly.
tests/hard_coded/int_impl_imports.exp:
tests/hard_coded/int_impl_imports.m:
tests/hard_coded/int_impl_imports_2.m:
A new test case to see whether we can compile a module that has
"int used, imp imported" references to another module, and has
unqualified references to an imported entity in the implementation.
tests/invalid/int_impl_imports.err_exp:
tests/invalid/int_impl_imports.m:
tests/invalid/int_impl_imports_2.m:
A new test case to see whether we can generate the right error message
for a module that has "int used, imp imported" references to another
module, and has an unqualified references to an imported entity
in the interface.
tests/hard_coded/Mmakefile:
tests/invalid/Mmakefile:
Enable the two new test cases.
tests/valid_seq/int_impl_imports.m:
tests/valid_seq/int_impl_imports_2.m:
Add vim mode lines.
If a module m1 imports module m2 using a use_module declaration in its
interface section but also imports it using an import_module declaration
in its implementation section, then references to entities defined in m2
in the interface of m1 must be module qualified, but similar references
in the implementation of m1 need NOT be module qualified.
The Mercury compiler has long had a bug that allowed entities imported
in the implementation of module m1 to be used in the interface of m1,
against the rules of the language. When I fixed that bug on 2015 nov 11,
the compiler became unable to properly process the situation described
in the paragraph above, because it still had another bug, which was that
it had a single setting for module qualification requirements: either it
was required *everywhere* in m1, or it was required *nowhere* in m1.
This diff fixes that bug (mantis bug 401) by allowing different requirements
in this respect in the interface of m1 versus its implementation.
It also changes the de-facto meaning of what exactly a use_module declaration
requires. The reference manual says only:
Uses of entities imported using @code{use_module} declarations
@emph{must} be explicitly module qualified.
This WAS unambiguous when it was written in june 1997, a few months before
submodules were added to the language. With a flat module system, there were
no nested module names, so either the module name was present, or it wasn't.
In the presence of nested modules, though, it IS ambiguous: HOW MUCH of
the module name must be present? The reference manual is silent on this.
At the moment, in the presence of a use_module for module ma.mb.mc,
a predicate p1 in ma.mb.mc may of course be referred to as ma.mb.mc.p1,
but may also be referred to as mb.mc.p1, or even just mc.p1. The specification
of mc is always required, but exactly WHICH of the previous module name
components are required depends on whether e.g. ma or ma.mb were themselves
imported via use_module or import_module declarations. The code implementing
the check (find_matches_in_permissions_map in module_qual.id_set.m) is itself
not too clear.
This diff changes the rules so that all references to anything imported
via a use_module declarations have to be fully qualified. This is stricter
than the existing rule, but it is MUCH simpler, and it better matches
the original intent of use_module declarations, which is the avoidance
of ALL POSSIBILITY of ambiguity.
NEWS:
doc/reference_manual.texi:
Document this change to the language.
compiler/prog_item.m:
Change the representation of sections in .int* files. Previously,
we recorded whether the interface file that the section was from
was read for an `import_module' or a `use_module' declaration.
We now allow the recording of the fact that it had both declarations,
a use_module in the interface and an import_module in the implementation.
compiler/modules.m:
Treat modules that have both a `use_module' declaration in interface
and an `import_module' declaration in the implementation as being of this
new internal section kind.
Add some infrastructure for debugging similar problems in the future.
compiler/module_qual.id_set.m:
Change the permissions system. Instead of recording *independently*
whether (a) an entity may be used in the interface and (b) whether
references to it must be qualified, record *separately* whether
(a) it may be used in the interface, and if so with what qualification
requirements, and (b) what its qualification requirements are in the
implementation. Unlike the old permission setup, the new one allows us
to express the "use_module in interface, import_module in implementation"
situation.
Implement the change to the language, by requiring full module
qualification of entities imported via use_module declarations.
This allows us to use a single parameterized piece of code to handle
both unqualified and qualified references, whereas before we used
separate pieces of code for them.
Change the way we handle errors in module qualification. Instead of
looking only for precise matches only, and looking for the possible causes
of errors only if we find either no matches or two or more matches, we now
return the near-miss matches as well, the ones that we need to decide
on what error message we want to generate. While this is slightly slower,
it is *much* simpler, since it allows us to avoid duplicating the search
code: once for precise matches only, once for no-match errors, and once
for multiple-match errors.
compiler/module_qual.collect_mq_info.m:
Set permissions for symbol access according to the new permissions system.
Code that previously triggered the bug will use the new interface file
section kind, and can now have its permissions record correctly.
compiler/module_qual.qual_errors.m:
Use a single predicate to generate error messages for all situations
in which there is not a single precise match for a module qualification.
This allows us to diagnose multiple potential problems with a single
lookup.
Change the wording of an existing error message to avoid a possibly-untrue
implication.
compiler/hlds_data.m:
Rename a field of the type_defn type to better document its meaning.
compiler/make_hlds.m:
Document the meaning of the need_qualifier field in sec_infos.
compiler/add_type.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.m:
compiler/pred_table.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
Conform to the above changes.
mdbcomp/sym_name.m:
Add a utility predicate for use in looking for near-miss matches
in module qualification.
Make the documentation of a related predicate more precise.
tests/invalid/bad_instance.m:
tests/submodules/class.m:
tests/submodules/nested.m:
tests/submodules/nested3.m:
tests/submodules/parent.m:
Make names fully module qualified where the language rules now require it.
tests/submodules/deeply_nested.m:
Comment out a part of the test that tested the partially qualified names,
since these are now not allowed.
tests/invalid/errors.err_exp:
Expect a now-improved error message.
tests/invalid/test_nested.err_exp:
tests/invalid/transitive_import.err_exp:
tests/invalid/undef_type.err_exp:
Expect a now less-likely-to-mislead error message.
tests/valid_seq/int_impl_imports.m:
tests/valid_seq/int_impl_imports_2.m:
The test case for mantis bug 401.
tests/valid_seq/Mmakefile:
Enable the new test case.
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.id_set.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
The new submodules of module_qual.m.
compiler/module_qual.m:
Delete the stuff moved to the new submodules.
compiler/notes/compiler_design.html:
Document the new submodules.