mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-22 04:43:53 +00:00
dadf30718d6084962be37dae8b94de41aaee90e2
34 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bd8569fffb | Clarify the relationship between two predicates. | ||
|
|
2e951421dd |
Replace some bools with bespoke types.
compiler/globals.m:
compiler/write_module_interface_files.m:
As above.
compiler/error_util.m:
compiler/handle_options.m:
compiler/mercury_compile_main.m:
compiler/read_modules.m:
Conform to the changes in globals.m.
In mercury_compile_main.m, add an XXX.
|
||
|
|
c2f92d5454 |
Partition extensions into ".m" and "all others".
This is a first step towards a much finer grained partition.
compiler/file_names.m:
Split the ext type into ext_src and ext_other, as mentioned above.
Add the first predicate for checking whether a string falls into
a given category of extensions.
Add an XXX proposing a better solution for an old problem that does not
actually arise in practice.
compiler/compile_target_code.m:
Split the two-moded predicate maybe_pic_object_file_extension into
two separate one-mode predicates, one for each old mode. The
implementations of the two modes were already separate, because
the two modes already did different jobs: while one went from PIC
to an "extension", the other went from an "extension string" to PIC.
Until now, "extension" and "extension string" were equivalent;
after this diff, they aren't anymore.
Delete an unused argument.
compiler/make.util.m:
Split the two-moded predicate target_extension into
two separate one-mode predicates, one for each old mode,
for the same reason as maybe_pic_object_file_extension above:
the fact that "extension" and "extension string" are now distinct.
compiler/options_file.m:
Move debug infrastructure here from mercury_compile_main.m, to help
debug possible problems with options files. (I had such a problem
while writing this diff.)
Improve how progress messages are printed.
compiler/options.m:
Make an error message more useful.
compiler/mercury_compile_main.m:
Add infrastructure for debugging possible problems with command lines.
(I had such a problem while writing this diff.)
compiler/analysis.m:
Conform to the changes above. Put the arguments of some methods
into the same order as similar predicates in file_names.m.
compiler/find_module.m:
Conform to the changes above. Delete an unused argument,
compiler/analysis.file.m:
compiler/du_type_layout.m:
compiler/elds_to_erlang.m:
compiler/export.m:
compiler/fact_table.m:
compiler/file_kind.m:
compiler/generate_dep_d_files.m:
compiler/grab_modules.m:
compiler/llds_out_file.m:
compiler/make.build.m:
compiler/make.deps_set.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_file.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/module_cmds.m:
compiler/prog_foreign.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/source_file_map.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
|
||
|
|
52c0919975 |
Make filename extensions a separate type, ...
... to allow later changes to its definition.
compiler/file_names.m:
We used to represent filename extensions simply as strings. This meant
all calls to the predicates in file_names.m that convert module names
to file names with various suffixes had to go through a complicated
sequence of tests that effectively partition the extensions into
several classes, with all extensions in a class being treated the same
but different classes being treated differently. And since this general
translation process is quite convoluted (which is not helped by it
being spread across several predicates), it is very hard to construct
a correctness argument for it.
It would be better to represent the different classes of extensions
explicitly, in a du type, with each function symbol of that type
representing all the extensions in the corresponding class (in the sense
of the paragraph above). However, getting there in one diff would make
that diff far too hard to test and to review. So this first diff
starts by simply making extension a notag type.
The above is the first step in implementing one old XXX. This diff
fully implements another old XXX, which is to make the argument order
of several predicates friendly to higher order code.
Add infrastructure for profiling how often this code makes directories.
Delete an unused type.
Add comments outlining proposed future improvements.
compiler/analysis.file.m:
compiler/analysis.m:
compiler/compile_target_code.m:
compiler/du_type_layout.m:
compiler/elds_to_erlang.m:
compiler/export.m:
compiler/fact_table.m:
compiler/file_kind.m:
compiler/find_module.m:
compiler/generate_dep_d_files.m:
compiler/grab_modules.m:
compiler/llds_out_file.m:
compiler/make.build.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_file.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/module_cmds.m:
compiler/module_imports.m:
compiler/parse_tree_out.m:
compiler/prog_foreign.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
Conform to the change to file_names.m.
Consistently use "Ext" for the abstract representation of extensions
and "ExtStr" for their string representation.
In a few places, add "XXX EXT" where the code manipulates extensions
as strings in a way that potentially inferferes with the partition
of extensions into classes.
In a few places, rename predicates to avoid ambiguities. factor out
common code, delete unneeded arguments, replace bools with bespoke types,
and make similar minor improvements.
In a few places, remove rafe-isms, such as the use ^elem.
|
||
|
|
733d20ba36 | Fix bit-rot in comments. | ||
|
|
ac466a3531 |
Avoid almost all conversions to parse_tree_int.
For a while now, we have been generating interface files into
file-kind-specific parse trees, but we then converted those into
the generic parse_tree_int type for further processing, because
the old code for doing that further processing operated on
parse_tree_ints. This diff replaces most of that "further processing"
code with code that operates on int-file-kind-specific parse trees,
thus avoiding the cost of conversion. The main cost is not performance
(the effect of this change on compiler speed is negligible), but loss
of code clarity through the loss of invariants.
compiler/comp_unit_interface.m:
After generating a parse_tree_intN for N in {0,1,2,3}, do NOT convert it
to a generic parse_tree_int.
When constructing a parse_tree_int3 from a raw_compilation_unit,
guard against a situation where we could unintentionally create
a duplicate of an abstract type definition. The solution here
is not the most elegant possible, but a better one requires other
changes that don't really fit in this diff.
compiler/canonicalize_interface.m:
Put two large blocks of code (dealing with the canonicalization
of pred and mode declarations respectively) into their own predicates.
Expose a mechanism to standardize not the contents of a whole
interface file, but just the predicate and mode declarations in it.
(These are the tricky kinds of items to canonicalize, because sorting
a set of mode declarations can change the meaning of the program.)
This mechanism is just a specialized version of the existing machinery.
Since this diff leaves the existing machinery unused, the next diff
will delete it, and since that will probably leave a too-small module,
delete the whole module, after moving the remaining small piece of code
to the only module that uses it, parse_tree_out.m.
compiler/parse_module.m:
Instead of implementing actually_read_module_intN in terms of
actually_read_module_int, do the reverse, which avoids the unnecessary
conversion from parse_tree_intN to parse_tree_int.
compiler/parse_tree_out.m:
Provide predicates, output_parse_tree_intN, to write out parse_tree_intN,
not just a generic parse_tree_int.
Change the existing service routines, mercury_output_parse_tree_intN,
that do all the work of the above new predicates to write out the contents
of each parse tree in the canonical order, using the newly exposed
functionality in canonicalize_interface.m where needed. (Previously,
write_module_interface_files.m invoked canonicalize_interface.m to do this
before calling parse_tree_out.m.)
These service routines were originally written for debugging; make them
suitable for creating proper .intN files by removing unneeded output.
compiler/write_module_interface_files.m:
Call the newly provided predicates in parse_tree_out.m to output
interface files. To make this possible, break up the old predicate
actually_write_interface_file into smaller predicates, so that the
new predicates actually_write_interface_fileN can each call whichever
of these are relevant for the given interface-file-kind. (Some pieces
are relevant to only a subset of these kinds.)
compiler/convert_parse_tree.m:
Note the reason why this diff is not deleting the functions that convert
parse_tree_intN to parse_tree_int.
compiler/read_modules.m:
Note the reason why this diff is not deleting the functions that read in
generic parse_tree_ints.
|
||
|
|
9789375cc5 |
Make pre-HLDS passes use file-kind-specific parse trees.
Replacing item blocks file-kind-specific kinds of section markers with
file-kind-specific parse trees has several benefits.
- It allows us to encode the structural invariants of each kind of file
we read in within the type of its representation. This makes the detection
of any accidental violations of those invariants trivial.
- Since each file-kind-specific parse tree has separate lists for separate
kinds of items, code that wants to operate on one or a few kinds of items
can just operate on those kinds of items, without having to traverse
item blocks containing many other kinds of items as well. The most
important consequence of this is not the improved efficiency, though
that is nice, but the increased clarity of the code.
- The new design is much more flexible. For example, it should be possible
to record that e.g. an interface file we read in as a indirect dependency
(i.e. a file we read not because its module was imported by the module
we are compiling, but because its module was imported by *another* imported
module) should be used *only* for the purpose it was read in for. This should
avoid situations where deleting an import of A from a module, because it
is not needed anymore, leads the compiler to generate an error message
about a missing import of module B. This can happen if (a) module B
always *should* have been imported, since it is used, but (b) module A's
import of module B lead to module B's interface being available *without*
an import of B.
Specifically, this flexibility should enable us to establish each module's
.int file as the single source of truth about how values of each type
defined in that module should be represented. When compiling each source
file, this approach requires the compiler to read in that module's .int file
but using only the type_repn items from that .int file, and nothing else.
- By recording a single parse tree for each file we have read, instead of
a varying number of item blocks, it should be significantly easier to
derive the contents of .d files directly from the records of those
parse trees, *without* having to maintain a separate set of fields
in the module_and_imports structure for that purpose. We could also
trivially avoid any possibility of inconsistencies between these two
different sources of truth. (We currently fill in the fields used to
drive the generation of .d files using two different pieces of code,
one used for --generate-dependencies and one used for all other invocations,
and these two *definitely* generate inconsistent results, as the significant
differences in .d files between (a) just after an invocation of
--generate-dependencies and (b) just after any other compiler invocation
can witness.)
This change is big and therefore hard to review. Therefore in many files,
this change adds "XXX CLEANUP" comments to draw attention to places that
have issues that should be fixed, but whose fixes should come later, in
separate diffs.
compiler/module_imports.m:
The compiler uses the module_and_imports structure defined here
to go from a raw compilation unit (essentially a module to be compiled)
to an augmented compilation unit (a raw compilation unit together
with all the interface and optimization files its compilation needs).
We used to store the contents of both the source file and of
the interface and optimization files in the module_and_imports structure
as item blocks. This diff replaces all those item blocks with
file-kind-specific parse trees, for the reasons mentioned above.
Separate out the .int0 files of ancestors modules from the .intN
files for N>0 of directly imported modules. (Their item blocks
used to be stored in the same list.)
Maintain a database of the source, interface and optimization files
we have read in so far. We use it to avoid reading in interface files
if we have already read in a file for the same module that contains
strictly more information (either an interface file with a smaller
number as a suffix, or the source file itself).
Shorten some field names.
compiler/prog_item.m:
Define data structures for storing information about include_module,
import_module and use_module declarations, both in a form that allows
the representation of possibly erroneous code in actual source files,
and in checked-and-cleaned-up form which is guaranteed to be free
of the relevant kinds of errors. Add a block comment at the start
of the module about the need for this distinction.
Define parse_tree_module_src, a data structure for representing
the source code of a single module. This is different from the existing
parse_tree_src type, which represents the contents of a single source file
but which may contain *more* than one module, and also different from
a raw_compilation_unit, which is based on item blocks and is thus
unable to express to invariants such as "no clauses in the interface".
Modify the existing parse_tree_intN types to express the distinction
mentioned just above, and to unify them "culturally", i.e. if they
store the same information, make them store it using the same types.
Fix a mistake by allowing promises to appear in .opt files.
I originally ruled them out because the code that generates .opt files
does not have any code to write out promises, but some of the predicates
whose clauses it writes out have goal_type_promise, which means that
they originated as promises, and get written out as promises.
Split the existing pragma item kind into three item kinds, which have
different invariants applying to them.
- The decl (short for declarative) pragmas give the compiler some
information, such as that a predicate is obsolete or that we
want to type specialize some predicate or function, that is in effect
part of the module's interface. Decl pragmas may appear in module
interfaces, and the compiler may put them into interface files;
neither statement is true of the other two kinds of pragmas.
- The impl (short for implementation) pragmas are named so
precisely because they may appear only in implementation sections.
They give the compiler information that is private to that module.
Examples include foreign_decls, foreign_codes, foreign_procs,
and promises of clause equivalence, and requests for inlining,
tabling etc. These will never be put into interface files,
though some of them can affect the compilation of other modules
by being included in .opt files.
- The gen (short for generated) pragmas can never (legally) appear
in source files at all. They record the results of compiler
analyses e.g. about which arguments of a predicate are unused,
or what exceptions a function can throw, and accordingly they
should only ever occur in compiler-generated interface files.
Use the new type differences between the three kinds of pragmas
to encode the above invariants about which kinds of pragmas can appear
where into the various kinds of parse trees.
Make the augmented compilation unit, which is computed from
the final module_and_imports structure, likewise switch from
storing item blocks to storing the whole parse trees of the
files that went into its construction. With each such parse tree,
record *why* we read it, since this controls what permissions
the source module being compiled has for access to the entities
in the parse tree.
Simplify the contains_foreign_code type, since one of three
function symbols was equivalent to one possible use of another
function symbol.
Provide a way to record which method of which class a compiler-generated
predicate is for. (See hlds_pred.m below.)
Move the code of almost all utility operations to item_util.m
(which is imported by many fewer modules than prog_item.m),
keeping just the most "popular" ones.
compiler/item_util.m:
Move most of the previously-existing utility operations here from
prog_item.m, most in a pretty heavily modified form.
Add a whole bunch of other utility operations that are needed
in more than one other module.
compiler/convert_parse_tree.m:
Provide predicates to convert from raw compilation units to
parse_tree_module_srcs, and vice versa (though the reverse
shouldn't be needed much longer).
Update the conversion operations between the general parse_tree_int
and the specific parse_tree_intN forms for the changes in prog_item.m
mentioned above. In doing so, use a consistent approach, based on
new operations in item_util.m, to detect errors such as duplicate
include_module and import/use_module declarations in all kinds
of parse trees.
Enforce the invariants that the types of parse trees of various kinds
can now express in types, generating error messages for their violations.
Delete some utility operations that have been moved to item_util.m
because now they are also needed by other modules.
compiler/grab_modules.m:
Delete code that did tests on raw compilation units that are now done
when that raw compilation unit is converted to a parse_tree_module_src.
Use the results of the checks done during that conversion to decide
which modules are imported/used and in which module section.
Record a single reason for why we reading in each interface and
optimization file. The code of make_hlds_separate_items.m will use
this reason to set up the appropriate permissions for each item
in those files.
Use separate code for handling different kinds of interface and
optimization files. Using generic traversal code was acceptable economy
when we used the same data structure for every kind of interface file,
but now that we *can* express different invariants for different kinds
of interface and optimization file, we want to execute not just different
code for each kind of file, but the data structures we want to work on
are also of different types. Using file-kind-specific code is a bit
longer, but it is significantly simpler and more robust, and it is
*much* easier to read and understand.
Delete the code that separates the parts of the implementation section
that are exported to submodules, and the part that isn't, since that task
is now done in make_hlds_separate_items.m.
Pass a database of the files we have read through the relevant predicates.
Give some predicates more meaningful names.
compiler/notes/interface_files.html:
Note a problem with the current operation of grab_modules.
compiler/get_dependencies.m:
Add operations to gather implicit references to builtin modules
(which have to be made available even without an explicit import_module
or use_module declaration) in all kinds of parse trees. These have
more code overall, but will be at runtime, since we need only look at
the item kinds that may *have* such implicit references.
Add a mechanism to record the result of these gathering operations
in import_and_or_use_maps.
Give some types, function symbols, predicates and variables
more meaningful names.
compiler/make_hlds_separate_items.m:
When we stored the contents of the source module and the
interface and optimization files we read in to augment it
in the module_and_imports structure as a bunch of item blocks,
the job of this module was to separate out the different kinds of items
in the item blocks, returning a single list of each kind of item,
with each such item being packaged up with its status (which encodes
a set of permissions saying what the source module is allowed
to do with it).
Now that the module_and_imports structure stores this info in
file-kind-specific parse trees, all of which have separate lists
for each kind of item and none of which contain item blocks,
the job of this module has changed. Now its job is to convert
the reason why each file was read in into the (one or more) statuses
that apply to the different kinds of items stored in it, wrap up
each item with its status, and return the resulting overall list
of status/item pairs for each kind of item.
compiler/read_modules.m:
Add predicates that, when reading an interface file, return its contents
in the tightest possible file-kind-specific parse tree.
Refine the database of files we have read to allow us to store
more file-kind-specific parse trees.
Don't require that files in the database have associated timestamps,
since in some cases, we read files we can put into the database
*without* getting their timestamps.
Allow the database to record that an attempt to read a file failed.
compiler/split_parse_tree_src.m:
Rearchitect how this module separates out nested submodules from within
the main module in a file.
Another of the jobs of this module is to generate error messages for
when module A includes module B twice, whether via nesting or via
include_module declarations, with one special exception for the case
where A's interface contains nested submodule A.B's interface,
and A's implementation contains nested submodule A.B's implementation.
The problem ironically was that while it reported duplicate include_module
declarations as errors, split_parse_tree_src.m also *generated*
duplicate include_module declarations. Since it replaced each nested
submodule occurrence with an include_module declaration, in the scenario
above, it generated two include_module declarations for A.B. Even worse,
the interface incarnation of submodule A.B could contain
(the interface of) its own nested submodule A.B.C, while its
implementation incarnation could contain (the implementation section of)
A.B.C. Each occurrence of A.B.C would be its only occurrence in the
including part of its parent A.B, which means local tests for duplicates
do not work. (I found this out the hard way.)
The solution we now adopt adds include_module declarations to the
parents of any submodule only once the parse tree of the entire
file has been processed, since only then do we know all the
includer/included relationships among nested modules. Until then,
we just record such relationships in a database as we discover them,
reporting duplicates when needed (e.g. when A includes B twice
*in the same section*), but not reporting duplicates when not needed
(e.g. when A.B includes A.B.C in *different* sections).
compiler/prog_data.m:
Add a new type, pf_sym_name_and_arity, that exactly specifies
a predicate or function. It is a clone of the existing simple_call_id
type, but its name does NOT imply that the predicate or function
is being called.
Add XXXs that call for some other improvements in type names.
compiler/prog_data_foreign.m:
Give a type, and the operations on that type, a more specific name.
compiler/error_util.m:
Add an id field to all error_specs, which by convention should be
filled in with $pred. Print out the value in this field if the compiler
is invoked with the developer-only option --print-error-spec-id.
This allows a person debugging the compiler find out where in the code
an undesired error message is coming from significantly easier
than was previously possible.
Most of the modules that have changes only "to conform to the changes
above" will be for this change. In many cases, the updated code
will also simplify the creation of the affected error_specs.
Fix a bug that looked for a phase in only one kind of error_spec.
Add some utility operations needed by other parts of this change.
Delete a previously internal function that has been moved to
mdbcomp/prim_data.m to make it accessible in other modules as well.
compiler/Mercury.options:
Ask the compiler to warn about dead predicates in every module
touched by this change (at least in one its earlier versions).
compiler/add_foreign_enum.m:
Replace a check for an inappropriately placed foreign_enum declaration
with a sanity check, since with this diff, the error should be caught
earlier.
compiler/add_mutable_aux_preds.m:
Delete a check for an inappropriately placed mutable declaration,
since with this diff, the error should be caught earlier.
compiler/add_pragma.m:
Instead of adding pass2 and pass3 pragmas, add decl and impl and
generated pragmas.
Delete the tests for generated pragma occurring anywhere except
.opt files, since those tests are now done earlier.
Shorten some too-long predicate names.
compiler/comp_unit_interface.m:
Operate on as specific kinds of parse trees as the interface of this
module will allow. (We could operate on more specific parse trees
if we changed the interface, but that is future work).
Use the same predicates for handling duplicate include_module,
import_module and use_module declarations as everywhere else.
Delete the code of an experiment that shouldn't be needed anymore.
compiler/equiv_type.m:
Replace code that operated on item blocks with code that operates
on various kinds of parse trees.
Move a giant block of comments to the front, where it belongs.
compiler/hlds_module.m:
Add a field to the module_info that lets us avoid generating
misleading error messages above missing definitions of predicates
or functions when those definitions were present but were not
added to the HLDS because they had errors.
Give a field and its access predicates a more specific name.
Mark a spot where an existing type cannot express everything
it is supposed to.
compiler/hlds_pred.m:
For predicates which the compiler creates to represent a class method
(the virtual function, in OOP terms), record not just this fact,
but the id of the class and of the method. Using this extra info
in progress messages (with mmc -V) prevents the compiler from printing e.g.
% Checking typeclass constraints on class method
% Checking typeclass constraints on class method
% Checking typeclass constraints on class method
when checking three such predicates.
compiler/make.m:
Provide a slot in the make_info structure to allow the database
of the files we have read in to be passed around.
compiler/make_hlds_error.m:
Delete predicates that are needed in just one other module,
and have therefore been moved there.
compiler/make_hlds_passes.m:
Add decl, impl and generated pragma separately, instead of adding
pass2 and pass3 pragmas separately.
Do not generate error messages for clauses, initialises or finalises
in module interfaces, since with this diff, such errors should be
caught earlier.
compiler/mercury_compile_main.m:
compiler/recompilation.check.m:
Explicitly pass around the expanded database of parse trees
of files that have been read in.
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
Collect module qualification information, and do module qualification
respectively on parse trees of various kinds, not item blocks.
Take information about what the module may do with the contents
of each interface or optimization file from the record of why
we read that file, not from the section markers in item blocks.
Break up some too-large predicates by carving smaller ones out of them.
compiler/options.m:
Add an option to control whether errors and/or warnings detecting
when deciding what should go into a .intN file be printed,
thus (potentially) preventing the creation of that file.
Add commented-out documentation for a previously totally undocumented
option.
doc/user_guide.texi:
Document the new option.
NEWS:
Announce the new option.
Mention that we now generate warnings for unused import_module and
use_module declarations in the interface even if the module has
submodules.
compiler/write_module_interface_files.m:
Let the new option control whether we filter out any messages generated
when deciding what should go into a .intN file.
compiler/parse_item.m:
Delete actually_read_module_opt, since it is no longer needed;
its callers now call actually_read_module_{plain,trans}_opt instead.
Delete unneeded arguments from some predicates.
compiler/parse_module.m:
Delete some long unused predicates.
compiler/parse_pragma.m:
When parsing pragmas, wrap them up in the new decl, impl or generated
pragma kinds.
compiler/parse_tree_out.m:
Add predicates to write out each of the file-kind-specific parse trees.
compiler/parse_tree_out_pragma.m:
Add predicates to write out decl, impl and generated pragmas.
compiler/polymorphism.m:
Add a conditionally-enabled progress message, which can be useful
in tracking down problems.
compiler/prog_item_stats.m:
Conform NOT to the changes above beyond what is needed to let this module
compile. Let that work be done the next time the functionality of
this module is needed, by which time the affected data structures
maybe have changed further.
compiler/typecheck.m:
Fix a performance problem. With intermodule optimization, we read in
.opt files, some of which (e.g. list.opt and int.opt) contain promises.
These promises are read in as predicates with goal_type_promise,
but they do not have declarations of the types of their arguments
(since promises do not have declarations as such). Those argument types
therefore have to be inferred. That inference replaces the original
"I don't know" argument types with their actual types.
The performance problem is that when we change the recorded argument types
of a predicate, we require another loop over all the predicates in the
module, so that any calls to this predicate can be checked against
the updated types. This is as it should be for callable predicates,
but promises are not callable. So if all the *only* predicates whose
recorded argument types change during the first iteration to fixpoint
are promises, then a second iteration is not needed, yet we used to do it.
The fix is to replace the "Have the recorded types of this predicate
changed?" boolean flag with a bespoke enum that says "Did the checking
of this predicate discover a need for another iteration", and not
setting it when processing predicates whose type is goal_type_promise.
compiler/typecheck_errors.m:
Do not generate an error message for a predicate missing its clauses
is the clauses existed but were not added to the HLDS because they were
in the interface section.
When reporting on ambiguities (when a call can match more than one
predicate or function), sort the possible matches before reporting
them.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_mode.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/canonicalize_interface.m:
compiler/check_for_missing_type_defns.m:
compiler/check_parse_tree_type_defns.m:
compiler/check_promise.m:
compiler/check_raw_comp_unit.m:
compiler/check_typeclass.m:
compiler/common.m:
compiler/compile_target_code.m:
compiler/compiler_util.m:
compiler/dead_proc_elim.m:
compiler/deps_map.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/du_type_layout.m:
compiler/field_access.m:
compiler/find_module.m:
compiler/float_regs.m:
compiler/format_call.m:
compiler/goal_expr_to_goal.m:
compiler/handle_options.m:
compiler/hlds_out_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/inst_check.m:
compiler/intermod.m:
compiler/introduce_parallelism.m:
compiler/layout_out.m:
compiler/make.dependencies.m:
compiler/make.module_dep_file.m:
compiler/make_hlds_warn.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_llds_back_end.m:
compiler/ml_top_gen.m:
compiler/mmakefiles.m:
compiler/mode_errors.m:
compiler/mode_robdd.equiv_vars.m:
compiler/modes.m:
compiler/module_qual.qual_errors.m:
compiler/oisu_check.m:
compiler/old_type_constraints.m:
compiler/options_file.m:
compiler/parse_class.m:
compiler/parse_dcg_goal.m:
compiler/parse_goal.m:
compiler/parse_inst_mode_defn.m:
compiler/parse_inst_mode_name.m:
compiler/parse_mutable.m:
compiler/parse_sym_name.m:
compiler/parse_type_defn.m:
compiler/parse_type_name.m:
compiler/parse_type_repn.m:
compiler/parse_types.m:
compiler/parse_util.m:
compiler/parse_vars.m:
compiler/post_term_analysis.m:
compiler/post_typecheck.m:
compiler/prog_event.m:
compiler/prog_mode.m:
compiler/purity.m:
compiler/qual_info.m:
compiler/recompilation.version.m:
compiler/resolve_unify_functor.m:
compiler/simplify_goal.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/simplify_proc.m:
compiler/state_var.m:
compiler/stratify.m:
compiler/style_checks.m:
compiler/superhomogeneous.m:
compiler/table_gen.m:
compiler/term_constr_errors.m:
compiler/term_errors.m:
compiler/termination.m:
compiler/trace_params.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/write_deps_file.m:
compiler/xml_documentation.m:
Conform to the changes above.
mdbcomp/prim_data.m:
Move a utility function on pred_or_funcs here from a compiler module,
to make it available to other compiler modules as well.
scripts/compare_s1s2_lib:
A new script that helped debug this diff, and may help debug
similar diffs the future. It can compare (a) .int* files, (b) .*opt
files, (c) .mh/.mih files or (d) .c files between the stage 1 and
stage 2 library directories. The reason for the restriction
to the library directory is that any problems affecting the
generation of any of these kinds of files are likely to manifest
themselves in the library directory, and if they do, the bootcheck
won't go on to compile any of the other stage 2 directories.
tests/debugger/breakpoints.a.m:
tests/debugger/breakpoints.b.m:
Move import_module declarations to the implementation section
when they are not used in the interface. Until now, the compiler
has ignored this, but this diff causes the compiler to generate
a warning for such misplaced import_module declarations even modules
that have submodules. The testing of such warnings is not the point
of the breakpoints test.
tests/invalid/Mercury.options:
Since the missing_interface_import test case tests error messages
generated during an invocation of mmc --make-interface, add the
new option that *allows* that invocation to generate error messages.
tests/invalid/ambiguous_overloading_error.err_exp:
tests/invalid/max_error_line_width.err_exp:
tests/warnings/ambiguous_overloading.exp:
Expect the updated error messages for ambiguity, in which
the possible matches are sorted.
tests/invalid/bad_finalise_decl.m:
tests/invalid/bad_initialise_decl.m:
Fix programming style.
tests/invalid/bad_item_in_interface.err_exp:
Expect an error message for a foreign_export_enum item in the interface,
where it should not be.
tests/invalid/errors.err_exp:
Expect the expanded wording of a warning message.
tests/invalid/foreign_enum_invalid.err_exp:
Expect a different wording for an error message. It is more "standard"
but slightly less informative.
tests/invalid_submodules/children2.m:
Move a badly placed import_module declaration, to avoid having
the message the compiler now generates for it from affecting the test.
tests/submodules/parent2.m:
Move a badly placed import_module declaration, to avoid having
the message the compiler now generates for it from affecting the test.
Update programming style.
|
||
|
|
c0293832b7 |
Allow "mmc -C foo.m" when file.m contains module bar ...
... provided the source file map in Mercury.modules records this fact.
compiler/read_modules.m:
When asked to compile a given file, look up the name of the module
that we expect to find in that file in Mercury.modules, if it exists,
instead of just assuming that it corresponds *exactly* to the filename.
compiler/source_file_map.m:
Provide a predicate to provide the filename-to-modulename lookup
now needed by read_modules.m. (Previously, we had only modulename-to-
filename lookup.)
Make the code constructing some error messages easier to read.
tools/make_arena:
Copy compiler/Mercury.modules to the arena along with compiler/*.m.
(The motivation for this change was that I wanted to profile the
.profdeep compiler in workspace N by simply invoking "lmcN -C *.m"
in the arena directory.)
|
||
|
|
2dbf279ff9 |
Only search for source file matching fully qualified module name.
Delete now-obsolete code to search for a module in files matching
partially qualified versions of the module name.
compiler/find_module.m:
As above.
compiler/read_modules.m:
compiler/write_deps_file.m:
Conform to changes.
tests/invalid/bad_module_name.err_exp
tests/invalid/bad_module_name.m
tests/invalid/bad_module_name_sub.m -> tests/invalid/bad_module_name.sub.m:
Rename sub-module and its source file so that the source file will
be found.
|
||
|
|
44d2436556 | Delete an obsolete test, and move related code next to each other. | ||
|
|
615d2795c8 |
Take foreign_import_modules out of the item type.
compiler/prog_item.m:
Even though we express foreign import module declarations syntactically
as pragmas, semantically, they are much closer to import_module
declarations. This means that the treatment they require in most places
in the compiler is similar to the treatment of import_module declarations,
and quite different from the treatment of other kinds of items.
Therefore this diff takes foreign_import_module declarations (FIMs
for short) out of item type. From now on, in parse trees and their
components, FIMs are stored in data structures of their own, next to
import_module declarations.
compiler/parse_types.m:
Provide a mechanism for the parser to return FIMs as an entity kind
of its own, not as an item.
compiler/comp_unit_interface.m:
Conform to the changes above, and give a predicate a more specific name.
compiler/module_qual.m:
Conform to the changes above, and require .int3 files to contain no FIMs.
compiler/canonicalize_interface.m:
compiler/check_raw_comp_unit.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/hlds_module.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/module_imports.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qualify_items.m:
compiler/parse_module.m:
compiler/parse_pragma.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/split_parse_tree_src.m:
Conform to the changes above.
|
||
|
|
fef3a0cd18 |
Move all callers of init_module_and_imports to module_imports.m.
compiler/module_imports.m:
The predicate init_module_and_imports is one of the two principal ways
to construct a module_and_imports structure from scratch. Instead of
exporting *it*, export predicates at a higher level of abstraction,
so that later changes can change their implementation. The code
of these predicates come from init_module_and_imports' old call sites.
Since many of the old call sites did (minor variations of) the same thing
around those calls, this diff also factors out some of that common code.
compiler/read_modules.m:
Get the callers of the predicate that reads source files to give it
filenames both with and without the .m suffix. Without this, both the
predicate and its callers have to add the suffix.
compiler/deps_map.m:
compiler/generate_dep_d_files.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile_main.m:
Replace calls to init_module_and_imports, and surrounding code,
with calls to the new higher level predicates now exported by
module_imports.m.
Conform to the changes to read_modules.m as well.
|
||
|
|
d29183e5fb |
Improve error messages about unexpected module names.
When you get this message, the error may be in the module name that it
reports to be wrong, but it may be in the places that set the compiler's
expectations of what the name of the module should be. This latter is
very likely the case when one moves a module of the Mercury compiler
from one package to another. In such cases, the problems are the old modules
that continue to refer to the renamed module by its old name.
This diff includes in the error message the identities of the modules
that refer to the old name; these are the modules that establish the
expectation that is not met.
compiler/deps_map.m:
When tracing references from module A to module B.C (either because
A imports B.C, or because A = B and A includes C), record A as a source
of the expectation that any file that contains module C will have
B.C as module C's fully qualified name. Since a module is usually imported
by more than one other module, there may be several sources of such
expectations.
compiler/parse_module.m:
Require callers of the functions that read in modules from files
to specify the contexts of the places that establish the expectation
of the module's fully qualified name.
When the expectation is not met, include the contexts in the error message.
compiler/read_modules.m:
Pass those contexts through to parse_module.m.
compiler/find_module.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile_main.m:
compiler/modules.m:
compiler/recompilation.check.m:
Conform to the changes above.
tests/invalid/bad_module_name.err_exp:
Expect the updated error message.
|
||
|
|
1af5bcf2f1 |
Make module_name_to_file_name currying-friendly.
compiler/file_names.m:
Change the order of arguments of module_name_to_file_name and related
predicates to make it easier to construct closures from them. Delete
the previous higher-order-friendly versions, which the previous step
has made unnecessary.
compiler/compile_target_code.m:
compiler/elds_to_erlang.m:
compiler/export.m:
compiler/find_module.m:
compiler/generate_dep_d_files.m:
compiler/intermod.m:
compiler/llds_out_file.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/module_cmds.m:
compiler/modules.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
Conform to the change above. In several places, this means replacing
explicit lambda expressions with simple partial application of the
relevant predicates.
|
||
|
|
79108c2b6d |
Don't generate the same error message twice.
When a file is expected to contain module X but actually contains module Y,
we used to generate a message about this error twice: once when processing
the ':- module' marker at the start of the source file, and once just after
the whole source file has been parsed. The two error messages had the same
text, but one was conditional on the warn_wrong_module_name, and the other
was unconditional. Error_util.m cleaned up the duplication, but not generating
duplication is a better fix.
compiler/parse_module.m:
Make the error_spec for this error always conditional on the
warn_wrong_module_name option. Document why we do this.
compiler/read_modules.m:
Don't check for the wrong module name after the whole file has been parsed;
any such error would have been caught when the ':- module' marker was
processed.
compiler/error_util.m:
Note that we no longer need a workaround for the error message duplication
fixed by this diff.
|
||
|
|
7274f5930f |
Fix an infinite loop from "mmc --make wrong_module_name".
compiler/read_modules.m:
When reading in a module from a file, the source code in the file
may have the wrong module name, i.e. a module name different from
the one that the caller expected. In such cases, read_module_src
generated an error message, and returned the actual module name
in the parse tree.
As it happens, make.module_dep_file.m depends on the parse tree
containing the *expected*, not the *actual* module name in such cases;
if it doesn't, it goes into an infinite loop.
Since deps_map.m also depends on returning the expected module name
in such cases, while compiler invocations that don't involve either
--make or deps_map don't really care either way, make read_module_src
return the expected module name in the parse tree in such cases.
compiler/deps_map.m:
Remove old code that replaced the actual with the expected module name,
since it isn't needed anymore.
There is no regression test for this bug, because one symptom of its failure
is filling up /tmp with temporary files. (Not having mmc --make clean up
after itself in such cases is a separate problem.)
|
||
|
|
66356bae7b |
Make the predicates that find files handle streams explicitly.
compiler/file_util.m:
The predicates in this module that find the file containing a Mercury
module used to allow the caller to specify that if the file can be
successfully opened, then the current input stream should be set to
the resulting stream. This meant that callers had to save the original
current input stream *before* calling this predicate, and later restore it,
*without* anything in between that would signal to readers of the code
that the current input stream had ever been changed.
Replace each of these predicates with two predicates. One returns
the stream as an explicit part of an output argument, letting the caller
do with the stream what it wished (in some cases, that would mean
using it in I/O operations as *explicitly* passed parameters, which
would not require touching the identity of the current input stream),
giving it the responsibility to close the stream when it is done using it.
The other would close the stream immediately, not letting the caller know
that the file was ever opened. The two versions are distinguised both
by name and by return type.
compiler/find_module.m:
Make the same change to search_for_module_source. (This predicate was
the motivation for this change, because unlike the predicates in
file_util.m, its signature did NOT provide readers with any sort of clue
that the searched-for file would actually be opened, and that the
resulting stream would become the new current input stream.)
Clarify the code that tries to find the source file for a module
by dropping qualifiers from the module name by (a) giving the predicate
a more explicit name, and (b) separating the search from the code
that handles the failure of the search.
compiler/parse_module.m:
compiler/read_modules.m:
Change part of the interface between these two modules. This used to be
that code in read_modules.m passed closures to parse_module.m for it
to invoke, closures whose predicates were always one of the predicates
affected by the changes above. Simplify the interface by making
read_modules.m invoke those predicates directly, and simply pass
the results.
compiler/compile_target_code.m:
compiler/make.module_dep_file.m:
compiler/make.program_target.m:
compiler/mercury_compile_front_end.m:
compiler/mmc_analysis.m:
compiler/module_cmds.m:
compiler/options_file.m:
compiler/write_deps_file.m:
Conform to the changes above.
|
||
|
|
f1df5d2dd1 |
Give parsing-related modules more meaningful names.
The mapping from the old to the new module names is:
prog_io -> parse_module
prog_io_dcg -> parse_dcg_goal
prog_io_error -> parse_error
prog_io_find -> find_module
prog_io_goal -> parse_goal
prog_io_inst_mode_defn -> parse_inst_mode_defn
prog_io_inst_mode_name -> parse_inst_mode_name
prog_io_iom -> parse_types
prog_io_item -> parse_item
prog_io_mutable -> parse_mutable
prog_io_pragma -> parse_pragma
prog_io_sym_name -> parse_sym_name
prog_io_type_defn -> parse_type_defn
prog_io_type_name -> parse_type_name
prog_io_typeclass -> parse_class
prog_io_util -> parse_util
prog_io_vars -> parse_vars
unparse -> parse_tree_to_term
|
||
|
|
cc9912faa8 |
Don't import anything in packages.
Packages are modules whose only job is to serve as a container for submodules. Modules like top_level.m, hlds.m, parse_tree.m and ll_backend.m are packages in this (informal) sense. Besides the include_module declarations for their submodules, most of the packages in the compiler used to import some modules, mostly other packages whose component modules their submodules may need. For example, ll_backend.m used to import parse_tree.m. This meant that modules in the ll_backend package did not have to import parse_tree.m before importing modules in the parse_tree package. However, this had a price. When we add a new module to the parse_tree package, parse_tree.int would change, and this would require the recompilation of ALL the modules in the ll_backend package, even the ones that did NOT import ANY of the modules in the parse_tree package. This happened even at one remove. Pretty much all modules in every one of the backend have to import one or more modules in the hlds package, and they therefore have import hlds.m. Since hlds.m imported transform_hlds.m, any addition of a new middle pass to the transform_hlds package required the recompilation of all backend modules, even in the usual case of the two having nothing to do with each other. This diff removes all import_module declarations from the packages, and replaces them with import_module declarations in the modules that need them. This includes only a SUBSET of their child modules and of the non-child modules that import them. |
||
|
|
984683b267 |
Fix the invalid/func_class test case.
The failure was caused by an error message generated by prog_io.m about a
problem (a file containing the wrong module) being ignored by deps_map.m.
A different problem was that we detected and generated error messages for this
problem in several places, which had different expectations and had access
to different information, and (partially but not wholly as a result of that)
generated different text. This diff makes all the pieces of code that detect
this problem use the same code to generate an error message. (Having only
one place to *detect* the problem would be more trouble that it is worth;
it would replace a few simple pieces of code with one larger, more complex
piece of code that would still have to cover all the relevant use cases,
but now removed from the rest of the code handling those use cases as well.)
It would probably be a good idea to unify those use cases as much as possible,
but that would be a much more complex change.
compiler/prog_io.m.m:
Generalize the predicate that generates error messages for wrong module
names, check_module_has_expected_name, to make it usable from both
prog_io.m and read_modules.m.
Replace a piece of code that had the same job with a call to this
predicate.
compiler/read_modules.m.m:
When reading in source files, ignore the errors that arise from
trying to read nonexistent files if our caller asks us to do so
(since some callers are not sure about what file a module is stored in),
but if the file *is* found and opened, then do *not* ignore the
errors we generate in parsing its contents.
Call the generalized version of check_module_has_expected_name,
and pass it the info it needs (the context of the module declaration).
compiler/deps_map.m:
If the read-in module contains a different module name than expected,
we already generated an error message for it, which read_modules.m
now doesn't throw away, so we now just keep that message,
and don't generate a redundant one.
compiler/error_util.m:
When sorting error messages, we have, for a long time now, deleted
duplicates. However, two error messages can differ in one having
conditional inclusion of format components and the other always
including the same components. We don't want to get two copies
of the error message if the condition is true, so we now evaluate
the conditions before sorting the messages. This is needed because
the code in prog_io.m that generates error messages for wrong module names
has to work in different conditions that have different ideas of how
bad an error a wrong module name is.
Provide a mechanism (a new phase in error messages) to separate
error messages about wrong module names from other errors.
This was part of an earlier attempt at solving the same problem
using a different approach (generating a new error message about
the problem only if we haven't already generated a message about it),
but that approach had the problem that the text of the generated message
could differ if it was generated in more than place, making it hard
to write a good test case. (Hence the generalization of
check_module_has_expected_name: although in some situations it generates
unconditional and in other condition error messages, the text in those
messages is always the same.) However, the new phase doesn't hurt
anything, and may be useful later, e.g. to handle modules like
tests/invalid_purity/purity_nonsense2.m differently, so keep it.
tests/invalid/Mmakefile:
Execute the purity_nonsense2 test case without first generating its
dependencies. If we did generate its dependencies, then due to the
fact that we no longer ignore errors during that step, we would
get *only* those errors, and not also the ones discovered by parts
of the compiler invoked later, and which are also expected by
purity_nonsense2.err_exp.
tests/invalid/bad_module_name.err_exp:
Expect the updated text of the "wrong module name" error message.
tests/invalid/missing_interface_import2.{m,err_exp}:
Due to a missing :- interface declaration, this test case wasn't testing
what it was testing. Add the missing section marker, and expect the updated
line numbers.
tools/bootcheck:
Print an explicit message at the end of a successful bootchecks.
|
||
|
|
62ec97d443 |
Report imports shadowed by other imports.
If a module has two or more import_module or use_module declarations
for the same module, (typically, but not always, one being in its interface
and one in its implementation), generate an informational message about
each redundant declaration if --warn-unused-imports is enabled.
compiler/hlds_module.m:
We used to record the set of imported/used modules, and the set of
modules imported/used in the interface of the current module. However,
these sets
- did not record the distinction between imports and uses;
- did not allow distinction between single and multiple imports/uses;
- did not record the locations of the imports/uses.
The first distinction was needed only by module_qual.m, which *did*
pay attention to it; the other two were not needed at all.
To generate messages for imports/uses shadowing other imports/uses,
we need all three, so change the data structure storing such information
for *direct* imports to one that records all three of the above kinds
of information. (For imports made by read-in interface and optimization
files, the old set of modules approach is fine, and this diff leaves
the set of thus *indirectly* imported module names alone.)
compiler/unused_imports.m:
Use the extra information now available to generate a
severity_informational message about any import or use that is made
redundant by an earlier, more general import or use.
Fix two bugs in the code that generated warnings for just plain unused
modules.
(1) It did not consider that a use of the builtin type char justified
an import of char.m, but without that import, the type is not visible.
(2) It scanned cons_ids in goals in procedure bodies, but did not scan
cons_ids that have been put into the const_struct_db. (I did not update
the code here when I added the const_struct_db.)
Also, add a (hopefully temporary) workaround for a bug in
make_hlds_passes.m, which is noted below.
However, there are at least three problems that prevent us from enabling
--warn-unused-imports by default.
(1) In some places, the import of a module is used only by clauses for
a predicate that also has foreign procs. When compiled in a grade that
selects one of those foreign_procs as the implementation of the predicate,
the clauses are discarded *without* being added to the HLDS at all.
This leads unused_imports.m to generate an uncalled-for warning in such
cases. To fix this, we would need to preserve the Mercury clauses for
*all* predicates, even those with foreign procs, and do all the semantic
checks on them before throwing them away. (I tried to do this once, and
failed, but the task should be easier after the item list change.)
(2) We have two pieces of code to generate import warnings. The one in
unused_imports.m operates on the HLDS after type and mode checking,
while module_qual.m operates on the parse tree before the creation of
the HLDS. The former is more powerful, since it knows e.g. what types and
modes are used in the bodies of predicates, and hence can generate warnings
about an import being unused *anywhere* in a module, as opposed to just
unused in its interface.
If --warn-unused-imports is enabled, we will get two separate set of
reports about an interface import being unused in the interface,
*unless* we get a type or mode error, in which case unused_imports.m
won't be invoked. But in case we do get such errors, we don't want to
throw away the warnings from module_qual.m. We could store them and
throw them away only after we know we won't need them, or just get
the two modules to generate identical error_specs for each warning,
so that the sort_and_remove_dups of the error specs will do the
throwing away for us for free, if we get that far.
(3) The valid/bug100.m test case was added as a regression test for a bug
that was fixed in module_qual.m. However the bug is still present in
unused_imports.m.
compiler/make_hlds_passes.m:
Give hlds_module.m the extra information it now needs for each item_avail.
Add an XXX for a bug that cannot be fixed right now: the setting of
the status of abstract instances to abstract_imported. (The "abstract"
part is correct; the "imported" part may not be.)
compiler/intermod.m:
compiler/try_expand.m:
compiler/xml_documentation.m:
Conform to the change in hlds_module.m.
compiler/module_qual.m:
Update the documentation of the relationship of this module
with unused_imports.m.
compiler/hlds_data.m:
Document a problem with the status of instance definitions.
compiler/hlds_out_module.m:
Update the code that prints out the module_info to conform to the change
to hlds_module.m.
Print status information about instances, which was needed to diagnose
one of the bugs in unused_imports.m. Format the output for instances
nicer.
compiler/prog_item.m:
Add a convenience predicate.
compiler/prog_data.m:
Remove a type synonym that makes things harder to understand, not easier.
compiler/modules.m:
Delete an XXX that asks for the feature this diff implements.
Add another XXX about how that feature could be improved.
compiler/Mercury.options.m:
Add some more modules to the list of modules on which the compiler
should be invoked with --no-warn-unused-imports.
compiler/*.m:
library/*.m:
mdbcomp/*.m:
browser/*.m:
deep_profiler/*.m:
mfilterjavac/*.m:
Delete unneeded imports. Many of these shadow other imports, and some
are just plain unneeded, as shown by --warn-unused-imports. In a few
modules, there were a *lot* of unneeded imports, but most had just
one or two.
In a few cases, removing an import from a module, because it *itself*
does not need it, required adding that same import to those of its
submodules which *do* need it.
In a few cases, conform to other changes above.
tests/invalid/Mercury.options:
Test the generation of messages about import shadowing on the existing
import_in_parent.m test case (although it was also tested very thoroughly
when giving me the information needed for the deletion of all the
unneeded imports above).
tests/*/*.{m,*exp}:
Delete unneeded imports, and update any expected error messages
to expect the now-smaller line numbers.
|
||
|
|
ef44f50bee |
Eliminate the old module_defn item.
After my earlier changes to the item list, we used module_defns for only
two things: recording when one module includes another, and recording
when one module imports or uses another. After this diff, both those
pieces of information are stored separately in each item block.
This has two benefits.
The first benefit is that it allows us to use the type system to enforce
structural invariants about where include_module, import_module and use_module
declarations may appear. The one invariant that we now enforce is that
optimization files may not contain either include_module or import_module
declarations, though they may contain use_module declarations. I suspect that
there are also similar invariants about interface files, but finding them
requires something like this change.
The second benefit is that it allows traversals of item blocks to scan
only the part of the item block that may contain the object of interest.
While reading in interface and optimization files, we used to scan the
full item list several times to find included and imported modules; those
scans can now look at just the relevant information. Since the item lists
that need to be processed usually include all the declarations in a
substantial number of other modules, including some (such as list.m) that
have LOTS of declarations, the speedup can be substantial. On tools/speedtest,
the speedup is 1.5%.
compiler/prog_item.m:
Make the change described above.
Provide utility predicates on the new types representing include_module,
import_module and use_module declarations.
Move an old utility predicate from here to prog_io.m, since only prog_io.m
uses it.
compiler/module_imports.m:
Several fields of the module_imports type contained sets of module names,
but stored them as lists. Change these to actual sets, to distinguish them
from the lists whose order is actually important. (Basically, the order
of processing .trans_opt files is important, but the order in which
we read in .int0, .int3, .int2, .int and .opt files isn't.) In several
places, this also avoids the need for conversions of lists to sets
for set operations, and then back to lists.
compiler/modules.m:
This module had several predicates that processed list of module names.
Make these operate on sets of module names instead, and break each of them
into two predicates: one that decides whether there is a next module name,
and if yes whether it has been processed already, and one to do the actual
processing if needed. This avoid the need for excessive indentation.
The code that discovers what other modules' interface files may need
to be read is now simpler due to the updated item_block structure.
Remove the submodule whose job it was to discover what modules are included
in items or item blocks, since that task has now become trivial, and is
now done by a utility predicate in prog_item.m. Since this was the second
last submodule (of the original eight), the last submodule is now the
whole module. Therefore this module now has significantly greater cohesion
than it had before.
compiler/write_module_interface_files.m:
compiler/prog_io_item.m:
Parse include_module, import_module and use_module declarations as
markers, not as items.
compiler/prog_io.m:
Expect include_module, import_module and use_module declarations as
markers, not as items.
compiler/split_parse_tree_src.m:
Discover included submodules more simply with the updated item_block
structure.
compiler/compile_target_code.m:
Put the arguments of the predicates in this module in a more standard
order.
compiler/recompilation.version.m:
Conform to the above changes. Note a possible bug.
Use a bespoke type to replace some bools.
compiler/check_raw_comp_unit.m:
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/generate_dep_d_files.m:
compiler/get_dependencies.m:
compiler/hlds_module.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make.dependencies.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_to_mercury.m:
compiler/module_deps_graph.m:
compiler/module_qual.m:
compiler/prog_io_find.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/trans_opt.m:
compiler/write_deps_file.m:
Conform to the above changes.
mdbcomp/sym_name.m:
Provide a utility predicate to get the set of ancestors of a module
as a set as well as a list.
tests/invalid/exported_unify3.err_exp:
tests/invalid/ii_parent.ii_child.err_exp:
Update the expected error messages, which refer to line numbers in
.int0 files, which have now changed, as we now put all import_module
declarations before ordinary items.
(Error messages shouldn't refer to automatically generated files,
but that is a separate concern.)
|
||
|
|
c6521f9ec5 |
Store version number info separately from items.
We used to store such information in md_version_number module_defns
in the item list. This did not enforce the invariants we want for
version number records, which are that
- they can appear only in interface files, not source or optimization
files;
- only one such record can appear in each interface file; and
- there cannot be more than one such record for any given module
in any augmented compilation unit (which can contain information from
many interface files).
This change removes the md_version_number module_defn, and replaces it
with (a) a slot in the parse tree of interface files that may contain
the version number record of that module, and (b) a slot in augmented
compilation units that maps module names to the version number record
for the named module.
compiler/prog_item.m:
Make the change above.
compiler/recompilation.m:
Provide a type for mapping module names to the named module's version
number record.
compiler/prog_io_item.m:
Parse version number records not as items, but as a new kind of marker.
compiler/prog_io.m:
Process this new marker. Record the first one in interface files.
Generate error messages for any later records in any given interface file,
or for any such records at all in any file of any other kind.
Since the contents of interface files are automatically generated,
users should never see the first of these kinds of messages.
They should never see the second of these kinds of messages either,
unless they hand-write a version number record, which is actually
pretty hard to do, not least since the format is undocumented :-(
compiler/make_hlds_passes.m:
Process the version number records separately from the items, since
they are now stored separately.
compiler/module_imports.m:
Provide a mechanism for collecting version number information
as interface files are read in.
compiler/modules.m:
Use that mechanism, and collect version number information
as interface files are read in.
compiler/recompilation.check.m:
compiler/recompilation.version.m:
Get the version number information these modules work with from the
new slot in parse_tree_ints.
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/hlds_module.m:
compiler/make.module_dep_file.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/read_modules.m:
compiler/split_parse_tree_src.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
|
||
|
|
2856408ab0 |
Separate the different kinds of sections in aug_comp_units.
When we create augmented compilation units, the item blocks in that
augmented unit come from five sources:
- the original raw compilation unit, containing the source code of a module;
- the interface files of the modules directly imported by that module;
- the interface files of the modules indirectly imported by that module;
- the optimization files needed by that module; and
- the interface files needed by those optimization files.
Change the representation of augmented compilation units so that instead of
containing one list of item blocks, each of which had a general section type,
it now has five lists of item blocks, one for each category above, with
a section type specialized to the category.
After this change, the compiler can process just the item blocks it wants
to process, instead of having to process all the item blocks, all the while
filtering out the irrelevant blocks. This filtering used to be order dependent,
with the ams_transitively_imported section marker, which derived from the old
md_transitively_imported module_defn, marking the dividing line between
the first and second categories on the one hand and the third, fourth and fifth
categories on the other hand. That marker is now gone, and the item blocks
in each category have no need to be in a specific order.
compiler/prog_item.m:
Make the above change in the representation of the augmented compilation
unit.
compiler/module_imports.m:
Instead of recording one list of item blocks for the augmented compilation
unit being built, record five.
compiler/modules.m:
Instead of always adding new item blocks to the one list, add it to the
relevant list. For modules.m, this will be one of the three item block
lists for interface files.
Provide a mechanism for getting back the augmented compilation unit
whole, once its building has finished.
compiler/intermod.m:
compiler/trans_opt.m:
Instead of always adding new item blocks to the one list, add it to the
relevant list. For intermod.m and trans_opt, this will be the item block
list for optimization files.
compiler/status.m:
Change the section types to account for the new kinds of sections
in augmented compilation units (from source, interface and optimization
files respectively).
Besides recording which module the item blocks in interface and
optimization sections came from, record the int_file_kind or opt_file_kind
as well. The compiler does not use this extra information (yet); I am
adding it so that I can look for further invariants.
compiler/file_kind.m:
A new module carved out of prog_item.m, containing the types that define
kinds of source, interface and optimization files, and the predicates that
operate on them. This needs to be a new module, because (a) status.m now
needs access to file kinds, (b) status.m should not import prog_item.m,
since that would lead to circular imports, and (c) the file kinds
don't belong with statuses.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Mention the new module.
compiler/equiv_type.m:
Conform to the changes above.
Replace the eqv_type_location type with the maybe_record_sym_name_use type,
since the location (in this module's interface, in this module's
implementation, in some other module) matters only for recording the uses
of sym_names.
compiler/make_hlds_passes.m:
Process all five lists of item blocks in each of the three passes.
Note cases where this may not be needed.
compiler/module_qual.m:
Conform to the changes above. Module qualify only the items in this
module, not the items we got from other modules.
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/hlds_module.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/mercury_to_mercury.m:
compiler/split_parse_tree_src.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
|
||
|
|
f2043fc9bd |
Replace the item list with more structured ASTs.
The parts of the compiler that run before the HLDS is constructed used to use
a raw list of items to represent source files (.m), interface files (.int0,
.int3, .int2 and .int) and optimization files (.opt, and .trans_opt).
These lists had structure, but this structure was implicit, not explicit,
and its invariants were never really documented.
This diff changes that. It replaces the item list with FIVE separate types.
Three of these each represent the unprocessed content of one file:
- parse_tree_int represents the contents of one interface file;
- parse_tree_opt represents the contents of one optimization file;
- parse_tree_src represents the contents of one source file.
Two of these each represent the processed contents of one or more files:
- raw_compilation_unit represents the contents of one module in a source file.
(The source file may contain several nested modules; the compilation unit
represents just one.)
- aug_compilation_unit represents the contents of one module in a source file,
just like raw_compilation_unit, but it is augmented with the contents of the
interface and optimization files of the other modules imported (directly or
indirectly) by the original module.
These five separate concepts all used to be represented by the same type,
list(item), but different invariants applied to the structure of those lists.
The most important of those invariants at least are now explicit in the types.
I think it is entirely possible that there are other invariants I haven't
discovered and documented (for example, .int3 files must have stricter
invariants on what can appear in them than .int files), but discovering
and documenting these should be MUCH easier after this change.
I have marked many further opportunities for improvements with "XXX ITEM_LIST".
Some of these include moving code between modules, and the creation of new
modules. However, I have left acting on those XXXs until later, in order to
keep the size of this diff down as much as possible, for easier reviewing.
compiler/prog_item.m:
Define the five new AST types described above, and utility predicates
that operate on them.
In the rest of this change, I tried, as much as possible, to change
predicates that used to take item lists as arguments to make them change
one of these types instead. In many cases, this required putting
the argument lists of those predicates into a more consistent order.
(Often, predicates that operated on the contents of the module
took the name of the module and the list of items in the module
not just as separate arguments, but as separate arguments that
weren't even next to each other.)
Define types that identify the different kinds of interface and
optimization files (.int, .int2 etc). These replace the string suffixes
we used to use to identify file types. Predicates that used to take strings
representing suffixes as arguments now have to specify whether they can
handle all these file types (source, interface and optimization),
or just (e.g.) all interface file types.
We used to have items corresponding to `:- module' and `:- end_module'.
Delete these; this information is now implicit in the structure of the
relevant AST. The parser handles the corresponding terms as markers,
not items; these markers are live only during parsing.
We used to have module_defns corresponding to `:- interface' and
`:- implementation'. Delete these; this information is now also implicit
in the structure of the relevant AST. Delete also, for the same reason,
the module_defns used to mark the starts of sublists in the overall lists
of items whose items came from the interface files or optimization files
of other modules. The former are now markers during parsing. The latter
are never parsed, but are created directly, after parsing has been done.
Delete the pragma type for `:- pragma source_file'. This is never
needed later; it is now a marker during parsing.
Change the internal representation of `:- import' and `:- use'.
It used to store a list of module names, but that list was an actual list
only during parsing; after that, it always had exactly one element.
It now stores one module name, and the parser has a mechanism to convert
one read-in term to more than one item, for use with terms such as
`:- import_module a, b'.
Delete the internal representation of `:- export', which was never
implemented, since if it IS ever implemented, it will almost certainly
be in a different form, which will need different support.
Document some further opportunities for simplification, later.
(This diff is already more than big enough.)
compiler/prog_io_item.m:
Rewrite the top-level part of this module. Instead of returning an item
for every parsed term, distinguish between parsing items that end up
in item lists inside ASTs, and parsing markers that end up creating
the STRUCTURE of those ASTs.
compiler/prog_io.m:
Rewrite the meat of this module. Instead of reading in a simple item list,
we now have to read in three different parse trees with three different
grammars, each of which is more complex than a simple list.
compiler/read_modules.m:
We used to have a map that mapped file names to the contents of those
files. We now need three separate maps, for interface files, optimization
files and source files, due to their separate types.
(We don't actually use the map for optimization files, which seems
to be a potential performance bug. The root cause of that problem
us that while intermod.m and the grab_*modules part of modules.m do
similar jobs, they don't use the same mechanisms.)
Replace the read_module predicate with the predicates read_module_src
and read_module_int, since these now return different types.
To avoid having to create AST-type-specialized variants of
read_module_ignore_errors and read_module_if_changed, give each of
read_module_{src,int} arguments that optionally tell them to ignore errors
and/or to read the module only if changed (though the "and" part of
"and/or" should not be needed.) These options already existed, but
they weren't exported.
compiler/timestamp.m:
Define the type we use for this option in read_modules.
compiler/status.m:
New module, containing mostly
- stuff carved out of hlds_pred.m, which defines the import_status type,
and the predicates that operate on it;
- stuff carved out of make_hlds_passes.m, which defines the item_status
type and the predicates that operate on that; and
- stuff carved out prog_data.m, which defines the section (now
module_section) and import_locn types.
It also contains the new section kinds we now use to represent item blocks
that were imported from interface and optimization files.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Add status.m to the parse_tree package.
compiler/hlds_pred.m:
compiler/prog_data.m:
Remove the stuff now in status.m.
compiler/error_util.m:
Provide a mechanism to control the order of messages with respect to
ALL other messages, not just those that also specify ordering.
compiler/mercury_to_mercury.m:
Provide predicates for printing out parse_tree_* and *_compilation_unit,
since printing out a simple item list is no longer enough for debugging.
Pretty-print type definitions nicely.
Replace a boolean with a purpose-specific enum.
compiler/modules.m:
Rewrite virtually all this module to make it work on the new AST
representations. Generate more detailed error messages for duplicate
module inclusions. Note lots of possibilities for further improvements,
including in the documentation. Mark places I am still not sure about,
especially places where I am not sure *why* the code is doing
what it is doing.
compiler/module_imports.m:
This module stores the data structure in which we accumulate the stuff
imported into a compilation unit, i.e. it is in these data structures
that a raw_compilation_unit becomes an aug_compilation_unit. Modify
the data structure and the predicates that operate on it to work on the
new AST representations, not on an (apparently) simple list of items.
Avoid ambiguities by adding a prefix to field names.
Add some convenience predicates.
compiler/module_qual.m:
Perform module qualification on both raw lists of items (for use when
generating .int3 files) but also on item blocks (for use pretty much
in every other situation).
Generate warnings about module imports that are unnecessarily in the
module interface using the module's context (the context of the `:- module'
declaration), not line 1 of the relevant file.
compiler/prog_io_error.m:
Split some error categories more finely, since some error kinds here
actually used to be reported for more than one distinct situation.
compiler/prog_io_util.m:
Provide utility predicates that operate on nonempty lists.
compiler/recompilation.version.m:
Make the comparison of the old and new contents of the interface file
work on two parse_tree_ints, not on two raw sequences of items.
Delete a boolean option that was always `yes', never 'no'.
compiler/recompilation.m:
Turn some functions into predicates to allow the use of state variable
notation.
Avoid ambiguities by adding a prefix to field names.
compiler/write_module_interface_files.m:
Besides updating the code in this module to work on the new parse tree
representations, also use cords instead of reversed lists in several cases.
Note many possibilities for further improvements.
library/list.m:
Move the type one_or_more here from the compiler directory, since
we now use it in more than one compiler module, and this is its natural
home.
mdbcomp/sym_name.m:
Rename "match_sym_name" to "partial_sym_name_matches_full", since this
better describes its job.
Add a det version of sym_name_get_module_name.
compiler/equiv_type.m:
Rename some types to make them more expressive.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_foreign_enum.m:
compiler/add_foreign_proc.m:
compiler/add_mode.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_special_pred.m:
compiler/add_type.m:
compiler/assertion.m:
compiler/base_typeclass_info.m:
compiler/check_typeclass.m:
compiler/ctgc.util.m:
compiler/dead_proc_elim.m:
compiler/dep_par_conj.m:
compiler/dependency_graph.m:
compiler/deps_map.m:
compiler/det_report.m:
compiler/elds_to_erlang.m:
compiler/equiv_type_hlds.m:
compiler/erl_code_gen.m:
compiler/export.m:
compiler/format_call.m:
compiler/higher_order.m:
compiler/hlds_data.m:
compiler/hlds_module.m:
compiler/hlds_out_pred.m:
compiler/inst_check.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/lco.m:
compiler/make.module_dep_file.m:
compiler/make_hlds.m:
compiler/make_hlds_error.m:
compiler/make_hlds_passes.m:
compiler/make_tags.m:
compiler/mercury_compile.m:
compiler/ml_proc_gen.m:
compiler/ml_type_gen.m:
compiler/mode_errors.m:
compiler/oisu_check.m:
compiler/par_loop_control.m:
compiler/polymorphism.m:
compiler/post_term_analysis.m:
compiler/post_typecheck.m:
compiler/pred_table.m:
compiler/prog_io_dcg.m:
compiler/prog_io_find.m:
compiler/prog_io_pragma.m:
compiler/prog_io_sym_name.m:
compiler/prog_io_type_defn.m:
compiler/prog_io_typeclass.m:
compiler/prop_mode_constraints.m:
compiler/push_goals_together.m:
compiler/qual_info.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/simplify_proc.m:
compiler/smm_common.m:
compiler/special_pred.m:
compiler/ssdebug.m:
compiler/stm_expand.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.versions.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/table_gen.m:
compiler/term_constr_initial.m:
compiler/term_constr_main.m:
compiler/termination.m:
compiler/trace_params.m:
compiler/trans_opt.m:
compiler/type_class_info.m:
compiler/type_ctor_info.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unify_proc.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/write_deps_file.m:
compiler/xml_documentation.m:
Conform to the changes above.
tests/hard_coded/higher_order_func_test.m:
tests/hard_coded/higher_order_syntax.m:
Avoid a warning about importing a module in the interface, not the
implementation.
tests/invalid/after_end_module.err_exp:
tests/invalid/any_mode.err_exp:
tests/invalid/bad_end_module.err_exp:
tests/invalid/bigtest.err_exp:
tests/invalid/bug113.err_exp:
tests/invalid/duplicate_modes.err_exp:
tests/invalid/errors.err_exp:
tests/invalid/errors1.err_exp:
tests/invalid/errors2.err_exp:
tests/invalid/funcs_as_preds.err_exp:
tests/invalid/inst_list_dup.err_exp:
tests/invalid/invalid_main.err_exp:
tests/invalid/missing_interface_import2.err_exp:
tests/invalid/no_exports.err_exp:
tests/invalid/occurs.err_exp:
tests/invalid/predmode.err_exp:
tests/invalid/prog_io_erroneous.err_exp:
tests/invalid/type_inf_loop.err_exp:
tests/invalid/typeclass_missing_det_3.err_exp:
tests/invalid/typeclass_test_11.err_exp:
tests/invalid/types.err_exp:
tests/invalid/undef_inst.err_exp:
tests/invalid/undef_mode.err_exp:
tests/invalid/undef_type.err_exp:
tests/invalid/unicode1.err_exp:
tests/invalid/unicode2.err_exp:
tests/invalid/vars_in_wrong_places.err_exp:
tests/warnings/unused_import.exp:
tests/warnings/unused_interface_import.exp:
Update the expected outputs in the invalid and warnings directories
to account for one or more of the following five changes.
Error messages that warn about a module not exporting anything
used to always refer to line 1 of the module's source file.
Now expect these messages to refer to the actual context of the module,
which is the context of its `:- module' declaration.
Expect a similarly updated context for messages that warn about
unnecessarily importing modules in the interface, not in the
implementation.
Expect a similarly updated context for messages that warn about
importing a module via both `:- import_module' and `:- use_module'.
For the modules that follow the `:- module' declaration directly with code,
also expect an error message about the missing section marker.
For modules that have terms after the `:- end_module' declaration,
replace "end_module" with "`:- end_module'" in the error message.
tests/invalid/func_class.{m,err_exp}:
New test case. It is a copy of the old tests/valid/func_class.m, which
is missing more than one module marker. The expected output is what I think
we should generate. The test case currently fails, because we currently
print only a subset of the expected errors. I am pretty sure the reason
for that is that old code I have not modified simply throws away the
missing error messages. Fixing this is work for the near future.
tests/invalid/Mmakefile:
Enable the new test case.
tests/misc_tests/pretty_print_test.exp:
Expect the pretty-printed output to use four-space indentation,
per our current style guide, since the compiler now generates such output.
tests/misc_tests/pretty_print_test.m:
Clean up the source code of the test as well.
tests/valid/complicated_unify.m:
tests/valid/det_switch.m:
tests/valid/easy_nondet_test.m:
tests/valid/error.m:
tests/valid/func_class.m:
tests/valid/func_int_bug_main.m:
tests/valid/higher_order.m:
tests/valid/higher_order2.m:
tests/valid/implied_mode.m:
tests/valid/indexing.m:
tests/valid/multidet_test.m:
tests/valid/nasty_func_test.m:
tests/valid/semidet_disj.m:
tests/valid/stack_alloc.m:
tests/valid/switches.m:
Add missing section markers to these modules. They used to follow
the `:- module' declaration directly with code.
|
||
|
|
38dc676f18 |
Record each kind of error when reading in files.
compiler/prog_io_error.m:
Replace the enum that used to record only whether we found no errors,
some nonfatal errors or some fatal errors, with a type that records
just what kinds of errors we found. Document each kind of error.
compiler/prog_io.m:
Record any errors using the new type. In some cases, we used to
forget fatal errors after finding nonfatal ones; now we don't.
compiler/read_modules.m:
Do not generate error messages about not being able to open a file
if we *could* open the file, but found other fatal errors inside it.
Factor out some common code.
compiler/intermod.m:
Ignore the error of not being able to open .opt files, but do not
ignore any other errors inside them. This fixes a long-standing piece
of strange-looking code.
compiler/module_imports.m:
Do not ignore old fatal errors if reading a new interface file
gets some new nonfatal errors. This fixes a long-standing XXX.
compiler/write_module_interface_files.m:
Do not ignore fatal errors when considering whether to write out interface
files. This fixes a long-standing XXX.
compiler/modules.m:
Generate better error messages for fatal errors inside modules
other than not being able to open the module.
compiler/deps_map.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/module_deps_graph.m:
compiler/recompilation.check.m:
compiler/trans_opt.m:
compiler/write_deps_file.m:
Conform to the change in prog_io_error.m.
|
||
|
|
13b6f03f46 |
Module qualify end_module declarations.
compiler/*.m:
Module qualify the end_module declarations. In some cases, add them.
compiler/table_gen.m:
Remove an unused predicate, and inline another in the only place
where it is used.
compiler/add_pragma.m:
Give some predicates more meaningful names.
|
||
|
|
2a518ce242 |
Break up compiler/prog_io.m.
Prog_io.m used to have three jobs.
- to manage the overall process of reading in the contents of source files;
- to search for the source files themselves; and
- to parse the top levels of items, particularly declarations.
This diff moves the code that does the second and third jobs into new modules
named prog_io_find.m and prog_io_item.m respectively. This improves the
cohesion of all three modules. It also moves the definition of the type
that records the result of the module-reading process into a new module
named prog_io_error.m, since several modules of the compiler need access
to it but not to any other part of the old prog_io.m.
compiler/prog_io_error.m:
compiler/prog_io_find.m:
compiler/prog_io_item.m:
New modules, with contents as above.
Note the faults of the module_error type.
compiler/prog_io.m:
Remove the stuff moved to other modules.
Document why the check_module_has_expected_name predicate is exported.
Add a predicate (peek_at_file) to avoid exposing the details of how
items are read to prog_io_find.m.
compiler/parse_tree.m:
Add the new modules.
compiler/notes/compiler_design.html:
Document the new modules.
compiler/timestamp.m:
Move the type maybe_return_timestamp here from prog_io.m. This is to avoid
situations where callers of predicates in read_modules.m need to import
prog_io.m just for the definition of this type, just because the predicate
in read_modules.m calls predicates in prog_io.m.
compiler/*.m:
Conform to the changes above.
|
||
|
|
500948d549 |
Break up mdbcomp/prim_data.m. The new modules have much better cohesion.
mdbcomp/sym_name.m:
New module, containing the part of the old prim_data.m that
dealt with sym_names.
mdbcomp/builtin_modules.m:
New module, containing the part of the old prim_data.m that
dealt with builtin modules.
mdbcomp/prim_data.m:
Remove the things that are now in the two new modules.
mdbcomp/mdbcomp.m:
deep_proiler/Mmakefile:
slice/Mmakefile:
Add the two new modules.
browser/*.m:
compiler/*.m:
deep_proiler/*.m:
mdbcomp/*.m:
slice/*.m:
Conform to the above changes.
|
||
|
|
022b559584 |
Make error messages for require_complete_switch scopes report the missing
Estimated hours taken: 8 Branches: main Make error messages for require_complete_switch scopes report the missing functors. Knowing which functors are missing requires knowing not only the set of functors in the switched-on variable's type, but also which of these functors have been eliminated by earlier tests, which requires having the instmap at the point of entry to the switch. Simplification, which initially detected unmet require_complete_switch requirements, does not have the instmap, and threading the instmap through it would make it significantly less efficient. So instead we now detect any problems with require_complete_switch scopes (and require_detism scopes, which are similar) during determinism checking. compiler/det_report.m: Factor out the code for finding the missing functors in conventional determinism errors, to allow it to be used for this new purpose. Check whether the requirements of require_complete_switch and require_detism scopes are met IF the predicate has any such scopes. compiler/det_analysis.m: compiler/det_util.m: Record whether the predicate has any such scopes. compiler/hlds_pred.m: Add a predicate marker that allows this recording. compiler/simplify.m: Delete the code that checks the require_complete_switch and require_detism scopes. Keep the code that deletes those scopes. (We have to do that here because determinism error reporting never updates the goal). compiler/prog_out.m: Delete an unused predicate. compiler/*.m: Remove unnecesary imports as flagged by --warn-unused-imports. |
||
|
|
4ebe3d0d7e |
Stop storing globals in the I/O state, and divide mercury_compile.m
Estimated hours taken: 60 Branches: main Stop storing globals in the I/O state, and divide mercury_compile.m into smaller, more cohesive modules. (This diff started out as doing only the latter, but it became clear that this was effectively impossible without the former, and the former ended up accounting for the bulk of the changes.) Taking the globals out of the I/O state required figuring out how globals data flowed between pieces of code that were often widely separated. Such flows were invisible when globals could be hidden in the I/O state, but now they are visible, because the affected code now passes around globals structures explicitly. In some cases, the old flow looked buggy, as when one job invoked by mmc --make could affect the globals value of its parent or the globals value passed to the next job. I tried to fix such problems when I saw them. I am not 100% sure I succeeded in every case (I may have replaced old bugs with new ones), but at least now the flow is out in the open, and any bugs should be much easier to track down and fix. In most cases, changes the globals after the initial setup are intended to be in effect only during the invocation of a few calls. This used to be done by remembering the initial values of the to-be-changed options, changing their values in the globals in the I/O state, making the calls, and restoring the old values of the options. We now simply create a new version of the globals structure, pass it to the calls to be affected, and then discard it. In two cases, when discovering reasons why (1) smart recompilation should not be done or (2) item version numbers should not be generated, the record of the discovery needs to survive this discarding. This is why in those cases, we record the discovery by setting a mutable attached to the I/O state. We use pure code (with I/O states) both to read and to write the mutables, so this is no worse semantically than storing the information in the globals structure inside the I/O state. (Also, we were already using such a mutable for recording whether -E could add more information.) In many modules, the globals information had to be threaded through several predicates in the module. In some places, this was made more difficult by predicates being defined by many clauses. In those cases, this diff converts those predicates to using explicit disjunctions. compiler/globals.m: Stop storing the globals structure in the I/O state, and remove the predicates that accessed it there. Move a mutable and its access predicate here from handle_options.m, since here is when the mutables treated the same way are. In a couple of cases, the value of an option is available in a mutable for speed of access from inside performance-critical code. Set the values of those mutables from the option when the processing of option values is finished, not when it is starting, since otherwise the copies of each option could end up inconsistent. Validate the reuse strategy option here, since doing it during ctgc analysis (a) is too late, and (b) would require an update to the globals to be done at an otherwise inconvenient place in the code. Put the reuse strategy into the globals structure. Two fields in the globals structure were unused. One (have_printed_usage) was made redundant when the one predicate that used it itself became unused; the other (source_file_map) was effectively replaced by a mutable some time ago. Delete these fields from the globals. Give the fields of the globals structure a distinguishing prefix. Put the type declarations, predicate declarations and predicate definitions in a consistent order. compiler/source_file_map.m: Record this module's results only in the mutable (it serves as a cache), not in globals structure. Use explicitly passed globals structure for other purposes. compiler/handle_options.m: Rename handle_options as handle_given_options, since it does not process THE options to the program, but the options it is given, and even during the processing of a single module, it can be invoked up the three times in a row, each time being given different options. (It was up to four times in a row before this diff.) Make handle_given_options explicitly return the globals structure it creates. Since it does not take an old global structure as input and globals are not stored in the I/O state, it is now clear that the globals structure it returns is affected only by the default values of the options and the options it processes. Before this diff, in the presence of errors in the options, handle_options *could* return (implicitly, in the I/O state) the globals structure that happened to be in the I/O state when it was invoked. Provide a separate predicate for generating a dummy globals based only on the default values of options. This allows by mercury_compile.m to stop abusing a more general-purpose predicate from handle_options.m, which we no longer export. Remove the mutable and access predicate moved to globals.m. compiler/options.m: Document the fact that two options, smart_recompilation and generate_item_version_numbers, should not be used without seeing whether the functionalities they call for have been disabled. compiler/mercury_compile_front_end.m: compiler/mercury_compile_middle_passes.m: compiler/mercury_compile_llds_back_end.m: compiler/mercury_compile_mlds_back_end.m: compiler/mercury_compile_erl_back_end.m: New modules carved out of the old mercury_compile.m. They each cover exactly the areas suggested by their names. Each of the modules is more cohesive than the old mercury_compile.m. Their code is also arranged in a more logical order, with predicates representing compiler passes being defined in the order of their invocation. Some of these modules export predicates for use by their siblings, showing the dependencies between the groups of passes. compiler/top_level.m: compiler/notes/compiler_design.html: Add the new modules. compiler/mark_static_terms.m: Move this module from the ml_backend package to the hlds package, since (a) it does not depend on the MLDS in any way, and (b) it is also needed by a compiler pass (loop invariants) in the middle passes. compiler/hlds.m: compiler/ml_backend.m: compiler/notes/compiler_design.html: Reflect mark_static_terms.m's change of package. compiler/passes_aux.m: Move the predicates for dumping out the hLDS here from mercury_compile.m, since the new modules also need them. Look up globals in the HLDS, not the I/O state. compiler/hlds_module.m: Store the prefix (common part) of HLDS dump file names in the HLDS itself, so that the code moved to passes_aux.m can figure out the file name for a HLDS dump without doing system calls. Give the field names of some structures prefixes to avoid ambiguity. compiler/mercury_compile.m: Remove the code moved to the other modules. This module now looks after only option handling (such as deciding whether to generate .int3 files, .int files, .opt files etc), and the compilation passes up to and including the creation of the first version of the HLDS. Everything after that is subcontracted to the new modules. Simplify and make explicit the flow of globals information. When invoking predicates that could disable smart recompilation, check whether they have done so, and if yes, update the globals accordingly. When compiling via gcc, we need to link into the executable the object files of any separate C files we generate for C code foreign_procs, which we cannot translate into gcc's internal structures without becoming a C compiler as well as a Mercury compiler. Instead of adding such files to the accumulating option for extra object files in the globals structure, we return their names using the already existing mechanism we have always used to link the object files of fact tables into the executable. Give several predicates more descriptive names. Put predicates in a more logical order. compiler/make.m: compiler/make.dependencies.m: compiler/make.module_target.m: compiler/make.module_dep_file.m: compiler/make.program_target.m: compiler/make.util.m: Require callers to supply globals structures explicitly, not via the I/O state. Afterward pass them around explicitly, passing modified versions to mercury_compile.m when invoking it with module- and/or task-specific options. Due the extensive use of partial application for higher order code in these modules, passing around the globals structures explicitly is quite tricky here. There may be cases where a predicate uses an old globals structure it got from a closure instead of the updated module- and/or task-specific globals it should be using, or vice versa. However, it is just as likely that, this diff fixes old problems by preventing the implicit flow of updated-only-for-one-invocation globals structures back to the original invoking context. Although I have tried to be careful about this, it is also possible that in some places, the code is using an updated-for-an-invocation globals structure in some but not all of the places where it SHOULD be used. compiler/c_util.m: compiler/compile_target_code.m: compiler/compiler_util.m: compiler/error_util.m: compiler/file_names.m: compiler/file_util.m: compiler/ilasm.m: compiler/ml_optimize.m: compiler/mlds_to_managed.m: compiler/module_cmds.m: compiler/modules.m: compiler/options_file.m: compiler/pd_debug.m: compiler/prog_io.m: compiler/transform_llds.m: compiler/write_deps_file.m: Require callers to supply globals structures explicitly, not via the I/O state. In some cases, the explicit globals structure argument allows a predicate to dispense with the I/O states previously passed to it. In some modules, rename some predicates, types and/or function symbols to avoid ambiguity. compiler/read_modules.m: Require callers to supply globals structures explicitly, not via the I/O state. Record when smart recompilation and the generation of item version numbers should be disabled. compiler/opt_debug.m: compiler/process_util.m: Require callers to supply the needed options explicitly, not via the globals in the I/O state. compiler/analysis.m: compiler/analysis.file.m: compiler/mmc_analysis.m: Make the analysis framework's methods take their global structures as explicit arguments, not as implicit data stored in the I/O state. Stop using `with_type` and `with_inst` declarations unnecessarily. Rename some predicates to avoid ambiguity. compiler/hlds_out.m: compiler/llds_out.m: compiler/mercury_to_mercury.m: compiler/mlds_to_c.m: compiler/mlds_to_java.m: compiler/optimize.m: Make these modules stop accessing the globals from the I/O state. Do this by requiring the callers of their top predicates to explicitly supply a globals structure. To compensate for the cost of having to pass around a representation of the options, look up the values of the options of interest just once, to make further access much faster. (In the case of mlds_to_c.m, the code already did much of this, but it still had a few accesses to globals in the I/O state that this diff eliminates.) If the module exports a predicate that needs these pre-looked-up options, then export the type of this data structure and its initialization function. compiler/frameopt.m: Since this module needs only one option from the globals, pass that option instead of the globals. compiler/accumulator.m: compiler/add_clause.m: compiler/closure_analysis.m: compiler/complexity.m: compiler/deforest.m: compiler/delay_construct.m: compiler/elds_to_erlang.m: compiler/exception_analysis.m: compiler/fact_table.m: compiler/intermod.m: compiler/mode_constraints.m: compiler/mode_errors.m: compiler/pd_util.m: compiler/post_term_analysis.m: compiler/recompilation.usage.m: compiler/size_prof.usage.m: compiler/structure_reuse.analysis.m: compiler/structure_reuse.direct.choose_reuse.m: compiler/structure_reuse.direct.m: compiler/structure_sharing.analysis.m: compiler/tabling_analysis.m: compiler/term_constr_errors.m: compiler/term_constr_fixpoint.m: compiler/term_constr_initial.m: compiler/term_constr_main.m: compiler/term_constr_util.m: compiler/trailing_analysis.m: compiler/trans_opt.m: compiler/typecheck_info.m: Look up globals information from the HLDS, not the I/O state. Conform to the changes above. compiler/gcc.m: compiler/maybe_mlds_to_gcc.pp: compiler/mlds_to_gcc.m: Look up globals information from the HLDS, not the I/O state. Conform to the changes above. Convert these modules to our current programming style. compiler/termination.m: Look up globals information from the HLDS, not the I/O state. Conform to the changes above. Report some warnings with error_specs, instead of immediately printing them out. compiler/export.m: compiler/il_peephole.m: compiler/layout_out.m: compiler/rtti_out.m: compiler/liveness.m: compiler/make_hlds.m: compiler/make_hlds_passes.m: compiler/mlds_to_il.m: compiler/mlds_to_ilasm.m: compiler/recompilation.check.m: compiler/stack_opt.m: compiler/superhomogeneous.m: compiler/tupling..m: compiler/unneeded_code.m: compiler/unused_args.m: compiler/unused_import.m: compiler/xml_documentation.m: Conform to the changes above. compiler/equiv_type_hlds.m: Give the field names of a structure prefixes to avoid ambiguity. Stop using `with_type` and `with_inst` declarations unnecessarily. compiler/loop_inv.m: compiler/pd_info.m: compiler/stack_layout.m: Give the field names of some structures prefixes to avoid ambiguity. compiler/add_pragma.m: Add notes. compiler/string.m: NEWS: Add a det version of remove_suffix, for use by new code above. |
||
|
|
cc1711071e |
Make all the pre-HLDS and front-end passes of the compiler gather up
Estimated hours taken: 50 Branches: main Make all the pre-HLDS and front-end passes of the compiler gather up all their error messages and print them all at once, in sorted order, unless the user asked for progress messages, in which case we print all the errors accumulated so far just before each printing each progress message. This should make error message output significantly easier to interpret. compiler/module_imports.m: Add a new field to the module_imports structure (the main pre-HLDS representation of the parse tree) to hold the list of error messages generated so far. Rename the module_imports structure as the module_and_imports structure, since it holds the module's items as well as information about its imports. Update the access predicates to encourage getting the items, the error messages and the error indication all at once. Add mechanisms for updating the error indication and the error messages. Add a distinguishing prefix to the field names of the structure. compiler/error_util.m: compiler/hlds_error_util.m: Add facilities for printing error messages in batches. In error_util.m, delete an unused argument from several predicates. compiler/mercury_compile.m: compiler/intermod.m: Gather up error messages to print in batches. In the parts of the code affected by the above, explicitly pass around a globals structure, instead of having all the predicates get it of the I/O state. Since some code (e.g. the start recompilation system) still uses the copy in the I/O state, we ensure that this copy is kept in sync with the explicitly passed around copy. Rename some predicates to avoid ambiguities. compiler/modules.m: Return errors in the module_and_imports structure, not separately. Gather up error messages to print in batches. Explicitly pass around globals structures. compiler/read_modules.m: Rename the read_modules type to have_read_module_map, since this is more explicit. For each module we have already read, remember not just the items we read from it, but also the error messages we generated during the reading. This is so these error messages can be printed together with other errors from other sources. Explicitly pass around globals structures. compiler/prog_io.m: compiler/purity.m: compiler/stratify.m: Rename several predicates to avoid ambiguities. compiler/modes.m: Change the interface of the main predicate to avoid the need for a lambda expression in mercury_compile.m. compiler/recompilation.check.m: Add a distinguishing prefix to the field names of a structure. Fix a wrong definition of this_file. Conform to the changes above. compiler/compiler_target_code.m: compiler/deps_map.m: compiler/make.m: compiler/make.dependencies.m: compiler/make.module_dep_file.m: compiler/make.module_target.m: compiler/make.program_target.m: compiler/make.util.m: compiler/make_hlds.m: compiler/make_hlds_passes.m: compiler/trans_opt.m: compiler/write_deps_file.m: Conform to the changes above. compiler/add_clause.m: compiler/add_pragma.m: compiler/state_var.m: Add an import of io, since their parent make_hlds.m does not import io anymore. In add_pragma, update an error message that did not mention trseg as well as tr as indicating a trailing grade. tests/hard_coded/Mmakefile: Move two tests that cannot pass in debug grades due to the lack of tail recursion to the list containing the other tests with this property. tests/invalid/test_feature_set.err_exp: Update the expected output of this test to expect the updated error message from add_pragma. tests/invalid/test_feature_set.err_exp2: Add this file as the expected output for trailing grades. tests/invalid/*.err_exp: tests/warnings/*.err_exp: Update the expected output for many tests to expect the error messages in sorted order. |
||
|
|
fc95b27671 |
Add search_for_file_mod_time which returns the last modification time
Branches: main
compiler/file_util.m:
Add search_for_file_mod_time which returns the last modification time
of the found file.
Add parameters to search_for_file and search_for_file_returning_dir
that chooses whether the found file should be left open as the input
stream on success.
Avoid dir.make_path_name where possible as it is slow.
compiler/make.util.m:
Use search_for_file_mod_time instead of something complicated.
compiler/file_names.m:
Make file_is_arch_or_grade_dependent not consider further clauses after
stripping the ".tmp" suffix off a filename.
compiler/compile_target_code.m:
compiler/make.module_dep_file.m:
compiler/make.program_target.m:
compiler/mercury_compile.m:
compiler/mmc_analysis.m:
compiler/module_cmds.m:
compiler/options_file.m:
compiler/prog_io.m:
compiler/read_modules.m:
compiler/write_deps_file.m:
Conform to changes.
|
||
|
|
a00596c283 |
The file modules.m contains lots of different kinds of functionality.
Estimated hours taken: 16 Branches: main The file modules.m contains lots of different kinds of functionality. While much of it belongs together, much of it does not. This diff moves most of the functionality that does not belong with the rest to several new modules: libs.file_util parse_tree.deps_map parse_tree.file_names parse_tree.module_cmds parse_tree.module_imports parse_tree.read_module parse_tree.write_deps_file To make them coherent, move some predicates from hlds.passes_aux, parse_tree.prog_io and parse_tree.prog_out to the new modules, making them more accessible, reducing the required access from the hlds package to parse_tree, or from the parse_tree package to libs. In the same spirit, this diff also moves some simple predicates and functions dealing with sym_names from prog_util.m to mdbcomp/prim_data.m. This allows several modules to avoid depending on parse_tree.prog_util. Rename some of the moved predicates and function symbols where this avoids ambiguity. (There were several that differed from other predicates or function symbols only in arity.) Replace several uses of bools with purpose-specific types. This makes some of the code significantly easier to read. This diff moves modules.m from being by far the largest module, to being only the seventh largest, from 8900+ lines to just 4200+. It also reduces the number of modules that import parse_tree.modules considerably; most modules that imported it now import only one or two of the new modules instead. Despite the size of the diff, there should be no algorithmic changes. compiler/modules.m: compiler/passes_aux.m: compiler/prog_io.m: compiler/prog_out.m: Delete the moved functionality. compiler/file_util.m: New module in the libs package. Its predicates search for files and do simple error or progress reporting. compiler/file_names.m: New module in the parse_tree package. It contains predicates for converting module names to file names. compiler/module_cmds.m: New module in the parse_tree package. Its predicates handle the commands for manipulating interface files of various kinds. compiler/module_import.m: New module in the parse_tree package. It contains the module_imports type and its access predicates, and the predicates that compute various sorts of direct dependencies (those caused by imports) between modules. compiler/deps_map.m: New module in the parse_tree package. It contains the data structure for recording indirect dependencies between modules, and the predicates for creating it. compiler/read_module.m: New module in the parse_tree package. Its job is reading in modules, both human-written and machine-written (such as interface and optimization files). compiler/write_deps_file.m: New module in the parse_tree package. Its job is writing out makefile fragments. compiler/libs.m: compiler/parse_tree.m: Include the new modules. compiler/notes/compiler_design.m: Document the new modules. mdbcomp/prim_data.m: compiler/prog_util.m: Move the predicates that operate on nothing but sym_names from prog_util to prim_data. Move get_ancestors from modules to prim_data. compiler/prog_item.m: Move stuff that looks for foreign code in a list of items here from modules.m. compiler/source_file_map.m: Note why this module needs to be in the parse_tree package. compiler/add_pred.m: compiler/add_special_pred.m: compiler/analysis.file.m: compiler/analysis.m: compiler/assertion.m: compiler/check_typeclass.m: compiler/compile_target_code.m: compiler/cse_detection.m: compiler/det_analysis.m: compiler/elds_to_erlang.m: compiler/exception_analysis.m: compiler/export.m: compiler/fact_table.m: compiler/higher_order.m: compiler/hlds_module.m: compiler/hlds_pred.m: compiler/intermod.m: compiler/llds_out.m: compiler/make.dependencies.m: compiler/make.m: compiler/make.module_dep_file.m: compiler/make.module_target.m: compiler/make.program_target.m: compiler/make.util.m: compiler/make_hlds_passes.m: compiler/maybe_mlds_to_gcc.pp: compiler/mercury_compile.m: compiler/mlds.m: compiler/mlds_to_c.m: compiler/mlds_to_gcc.m: compiler/mlds_to_ilasm.m: compiler/mlds_to_java.m: compiler/mmc_analysis.m: compiler/mode_constraints.m: compiler/mode_debug.m: compiler/modes.m: compiler/module_qual.m: compiler/optimize.m: compiler/passes_aux.m: compiler/proc_gen.m: compiler/prog_foreign.m: compiler/prog_io.m: compiler/prog_io_util.m: compiler/prog_mutable.m: compiler/prog_out.m: compiler/pseudo_type_info.m: compiler/purity.m: compiler/recompilation.check.m: compiler/recompilation.usage.m: compiler/simplify.m: compiler/structure_reuse.analysis.m: compiler/structure_reuse.direct.detect_garbage.m: compiler/structure_reuse.direct.m: compiler/structure_sharing.analysis.m: compiler/tabling_analysis.m: compiler/term_constr_main.m: compiler/termination.m: compiler/trailing_analysis.m: compiler/trans_opt.m: compiler/type_util.m: compiler/typecheck.m: compiler/typecheck_info.m: compiler/unify_proc.m: compiler/unused_args.m: compiler/unused_imports.m: compiler/xml_documentation.m: Minor changes to conform to the changes above. |