mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 05:13:48 +00:00
083d376e6598628362ee91c2da170febd83590f4
40 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
307b1dc148 |
Split up error_util.m into five modules.
compiler/error_spec.m:
This new module contains the part of the old error_util.m that defines
the error_spec type, and some functions that can help construct pieces
of error_specs. Most modules of the compiler that deal with errors
will need to import only this part of the old error_util.m.
This change also renames the format_component type to format_piece,
which matches our long-standing naming convention for variables containing
(lists of) values of this type.
compiler/write_error_spec.m:
This new module contains the part of the old error_util.m that
writes out error specs, and converts them to strings.
This diff marks as obsolete the versions of predicates that
write out error specs to the current output stream, without
*explicitly* specifying the intended stream.
compiler/error_sort.m:
This new module contains the part of the old error_util.m that
sorts lists of error specs and error msgs.
compiler/error_type_util.m:
This new module contains the part of the old error_util.m that
convert types to format_pieces that generate readable output.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Include and document the new modules.
compiler/error_util.m:
The code remaining in the original error_util.m consists of
general utility predicates and functions that don't fit into
any of the modules above.
Delete an unneeded pair of I/O states from the argument list
of a predicate.
compiler/file_util.m:
Move the unable_to_open_file predicate here from error_util.m,
since it belongs here. Mark another predicate that writes
to the current output stream as obsolete.
compiler/hlds_error_util.m:
Mark two predicates that wrote out error_spec to the current output
stream as obsolete, and add versions that take an explicit output stream.
compiler/Mercury.options:
Compile the modules that call the newly obsoleted predicates
with --no-warn-obsolete, for the time being.
compiler/*.m:
Conform to the changes above, mostly by updating import_module
declarations, and renaming format_component to format_piece.
|
||
|
|
f7355f708b |
Move var_db and var_{name,type}_source to var_db.m.
In the process, restrict the use of these types to just those modules
that need to provide services both other modules that use var_tables,
and modules that do not. The latter are modules that either can,
or always do, execute before var_tables are set up.
In some cases, code that previously operated on e.g. var_name_sources
had all its callers converted to use var_tables. In those cases, replace
the use of var_name_sources with var_tables directly.
In other cases, code that previously operated on e.g. var_name_sources
still has some callers that use varsets. In those cases,
- provide versions using var_tables if most callers use var_tables,
renaming predicates/functions to make this the version seem the default,
- leave the operation to work on var_name_sources if some its callers
also have only var_name_sources,
- if there are no such callers, keep just the two versions operating
on varsets and var_tables respectively.
compiler/var_db.m:
compiler/var_table.m:
Move the part of var_table.m that contains the definitions
of the above three types, and the operations on them, to the
new module var_db.m. Only 25 modules currently need var_db.m,
compared to 176 for var_table.m.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Add and document the new module.
compiler/parse_tree_out_term.m:
Add a "_vs" suffix to the names of operations that print variables
or terms using varsets, and reuse their old names for versions
that use var_table arguments. For the operations that need var_name_source
versions, make it just select between the varset and var_table versions.
compiler/hlds_out_goal.m:
compiler/instmap.m:
compiler/hlds_out_mode.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.m:
compiler/pd_info.m:
Change some predicates that used to operate on var_{name,type}_sources
to operate on var_tables.
In hlds_out_mode.m, delete some unused predicates, and stop exporting
a predicate whose only caller is local.
compiler/*.m:
Conform to the changes above.
|
||
|
|
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.
|
||
|
|
0f6941447e | Use simplest_spec and simplest_msg where appropriate. | ||
|
|
b0897e95d5 |
Replace pairs of lists with lists of pairs.
After this diff, the compiler allocates very slightly more memory,
but in exchange it has to do fewer nil/cons tests. The overall result
on my laptop is a very slight speedup. (The impact has to be limited,
because the code involved takes much less than 1% of the compiler's runtime.)
compiler/superhomogeneous.m:
The main predicate that breaks down terms into superhomogeneous form
used to introduce unifications between corresponding elements of two lists:
the list of argument terms in a call (maybe in the head of a clause,
or maybe in its body), and a freshly made corresponding list
of distinct variables. These lists had to have the same length,
but this was enforced only via runtime checks.
A variant of this predicate took a third input list as well,
specifying the contexts of these arguments. This also had to have
the same length, and again this was enforced only via runtime checks.
Replace this approach with one that processes a list of pairs
or triples, which encodes the "same length invariant" in the type.
Make the predicate that allocates the distinct variable for each arg
return the input needed by the new version of insert_arg_unifications.
compiler/hlds_goal.m:
Add a predicate to initialize a goal_info's context *and* purity,
for use by goal_expr_to_goal.m.
compiler/goal_expr_to_goal.m:
Conform to the change in superhomogeneous.m.
Factor out some comon code.
Use the new predicate in hlds_goal.m.
compiler/add_clause.m:
compiler/field_access.m:
compiler/state_var.m:
Conform to the change in superhomogeneous.m.
|
||
|
|
c1bdd2100b | Delete unneeded $module args from aborts. | ||
|
|
e08b8505e9 | Import the parents of *all* imported modules. | ||
|
|
5eae909f78 |
Split hlds_cons.m from hlds_data.m.
compiler/hlds_cons.m:
compiler/hlds_data.m:
Move the parts of hlds_data.m dealing with the cons table
(representing the function symbols visible in the current module)
and with the fields within those function symbols to the new module
hlds_cons.m. This code was a large fraction of hlds_data.m, yet it is
needed by relatively few modules.
compiler/hlds.m:
compiler/notes/compiler_design.html:
Add and document the new module.
compiler/*.m:
Import the new module as well as, or instead of, hlds_data.m.
|
||
|
|
253378fe21 |
Improve error messages for malformed lambda expressions.
Do this by insisting that terms whose top level(s) look like lambda
expressions should be parsed as lambda expressions, and return error
messages if that parsing attempt fails.
I did this is in several commits to modules in the parse_tree.m package
that translated terms to the parse tree, i.e. to goal_exprs. This diff
does the same thing for lambda expressions.
NEWS:
Document this change, as well as other, similar changes in the recent past.
compiler/superhomogeneous.m:
When translating a var-functor unification, which has the form
X = f(Y1, ..., Yn), to the HLDS, we parse the right hand side term,
looking for Mercury constructs such as lambda expressions and
field accesses. We used to do this by checking if the RHS was
a well-formed version of the construct we were looking for,
and falling back to parsing it as an ordinary term. That meant that
terms that the programmer *intended* to be lambda expressions,
but which contained a syntax error, were not diagnosed during the
construction of the HLDS, but during a later pass. Virtually always,
that later pass was typechecking. Since in such cases, the typechecker
is given terms whose function symbols were *intended* to be the "keywords"
of Mercury constructs (to the extent that Mercury *has* keywords),
not the names of data constructors or predicates, those error messages
were almost always confusing, and at best an *indirect* indication
of the actual problem with the code.
This diff changes things so that when the top function symbol on
the RHS of a unification is a Mercury "keyword" used only in lambda
expressions, we commit to parsing it as such. If the parsing fails,
we now generate an error message that describes the problem *directly*.
To make the task of generating good error messages easier, and to make it
possible to generate *consistent* error messages for the same error
in different contexts, unify the four separate pieces of code that
*used* to parse different kinds of lambda expressions. These four
pieces of code used to parse
- predicates defined using DCG notation;
- predicates defined using non-DCG notation;
- functions that used the default function mode and determinism; and
- functions that did not use the default function mode and determinism.
The unified code allows a function lambda expression to omit the
default argument modes *independently* of whether it omits the default
determinism, and vice versa. The old code did not do that: if you didn't
explicitly specify one, you couldn't explicitly specify the other either,
probably because it would have required two more pieces of code.
The language reference manual says, in section 8.1:
As with ‘:- func’ declarations, if the modes and determinism
of the function are omitted in a higher-order function term, then
the modes default to ‘in’ for the arguments, ‘out’ for
the function result, and the determinism defaults to ‘det’.
This text is vague on whether the modes and determinism are *allowed*
to be omitted independently. The old behavior was a strict reading
of this text. The new behavior follows the most liberal possible reading,
and thus allows all the behaviors that the old one did, and more.
Integrate the test for big integers that are too big to be represented
with the conversion of all ordinary functors into cons_ids, both to
simplify the code, and to speed it up. In the process, improve the
error message for too-big integers.
compiler/add_clause.m:
Don't try to generate warnings for singleton variables in a clause
if the clause had syntax errors. Part of the parser's recovery from
those syntax errors (e.g. when they occur in lambda expressions' clause
heads) may have included not translating parts of the original term
into the parsed clause body, so any such warnings could be misleading.
Such warnings could also be correct, but I expect most programmers
would prefer to miss some correct singleton warnings while the
syntax errors are present in their code, and get them only once
they have fixed those syntax errors, than to have to wade through
misleading errors messages for the initial syntax error to get to
the real ones.
compiler/field_access.m:
Clarify the text of an error message.
Delete a predicate that superhomogeneous.m no longer needs.
compiler/mercury_compile_front_end.m:
Don't proceed past typechecking if the parser found syntax errors,
since any errors we find later, e.g. as part of mode checking,
are quite likely to be avalanche errors caused by those syntax errors.
The reason why this wasn't a problem in the past is that when
the program contained malformed uses of builtin constructs such as
lambda expressions and field accesses, the parser used to simply
transform the terms containing the malformed constructs into the arguments
of call goals and unifications, and it was the typechecker that discovered
that these function symbols did not match any declared type.
The "type errors" generated for such problems told the compiler
not to run later compiler passes to prevent avalanche errors.
We now report syntax errors earlier, during the construction of the HLDS,
and it is entirely possible that the parser's recovery from those errors
leaves *no* type errors to be reported. This is why we need to make
the presence of syntax errors in a predicate block the invocation
of later passes.
compiler/typecheck.m:
Return whether the predicates we typechecked had syntax errors,
to make the change in mercury_compile_front_end.m possible.
compiler/state_var.m:
If a lambda expression has two or more arguments of the form !X,
we now print an error message for each, with each message naming the bad
state variable and giving the context of the argument. We used to
print only a single message saying that *some* argument misused
state variables this way. Similarly, we now print the correct context
for !X appearing as a function result, whether in a lambda expression
or at the top level of a clause.
The actual printing of those error messages takes place elsewhere,
but change the utility predicates exported by state_var.m to make
the change possible.
Change the error message we generate for !X appearing as a function
result, to avoid suggesting a possible repair that is virtually never
the right repair.
compiler/mode_util.m:
Delete a predicate that was used only by superhomogeneous.m; an updated
version of that predicate is now in superhomogeneous.m itself.
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
Instead of exporting predicates to module qualify the whole list of
argument modes of a lambda expression, export predicates that module
qualify only one such mode, since that is what superhomogeneous.m
now wants.
compiler/hlds_clauses.m:
Add access predicates for fields of the clauses_info type that previously
did not have them, including the one that records the presence of syntax
errors.
Put related fields of the clauses_info together.
Group both the declarations and the definitions of the access predicates
together, and put them in the same order as the fields themselves.
compiler/add_class.m:
compiler/add_pred.m:
compiler/add_pragma_type_spec.m:
compiler/higher_order.m:
compiler/hlds_pred.m:
compiler/unify_proc.m:
Conform to the changes above.
tests/invalid/lambda_syntax_error.err_exp:
Print one error message for each of the four malformed lambda expressions
in this test case, instead of the 13 avalanche messages we used to get
from the typechecker, which tried to interpret the malformed lambda
expression heads as calls, unifications etc.
The motivation for this diff was a set of similar set of avalanche error
messages for a real-life syntax error in a lambda expression in a change
I worked on a while ago.
tests/benchmarks/deriv.{m,exp}:
This test case used to use "^" as a data constructor (to represent
raising X to the Nth power). Since the parser now insists on treating it
as a field access operator, replace "^" with "power". (This test has
the excuse of predating the addition of field access syntax to Mercury
by several years.)
tests/dppd/grammar_impl.m:
This test case used to define a type which contained "is" as a data
constructor. After this diff, this is no longer allowed (as part of
"is detism", it looks to the parser like the top constructor in a
lambda expression head, and therefore as the top constructor of
the lambda expression as a whole if it has no body), so add the type
name as a prefix to this data constructor. To future-proof the test case,
do the same with the several other data constructors that also duplicate
the names of Mercury keywords.
tests/hard_coded/pprint_test2.{m,exp}:
tests/hard_coded/write.{m,exp}:
tests/hard_coded/write_binary.{m,exp}:
These test cases used to define a type which contained ":-" as a data
constructor. After this diff, this is no longer allowed, so replace them
with "?-". (The tests check how io.m formats terms whose data constructor
is an operator, so the replacement needs to be an operator, and Mercury
syntax does not use "?-"; library/ops.m lists it as an operator only
because it is an operator in Prolog.)
Update write_binary.m to conform to our current style guide, and to avoid
using the recently-deprecated io.make_temp.
tests/invalid/invalid_int.err_exp:
Expect the updated text of the error message for a too-big
integer constant.
tests/invalid/record_syntax_error.err_exp:
Expect the updated text of the error message for a malformed field name.
tests/invalid/state_vars_test3.err_exp:
Expect the updated text of the error message for a !X appearing
as the result of a lambda function.
tests/invalid/state_vars_test4.err_exp:
Expect the error message for a !X lambda argument, but (since we now
stop after typechecking in the presence of such syntax errors),
don't expect the avalanche error messages we used to print from the
mode checker.
|
||
|
|
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
|
||
|
|
74825f9d1c | Convert (C->T;E) to (if C then T else E). | ||
|
|
2f1ec6b91c |
Don't abort if a curried predicate has no declared determinism.
compiler/polymorphism.m:
When it sees a curried predicate call, polymorphism converts it to an
explicit lambda expression in order to add the unifications that
construct the type_infos and/or typeclass_infos the call needs.
For this, it needs to know the call's determinism. If the predicate had
no declared determinism, we used to abort the compiler, which is
too drastic a response to a simple programmer error.
Change this so that in this situation, we simply report an error,
and record that it is not safe to continue the compilation process.
In reality, it is not safe to continue the compilation only of the
predicate that the lambda expression occurs in, but in the vast, vast
majority of cases, this should be more than good enough.
I did try to code this change so that we continued the compilation
of other predicates when this error occurs, but it turned out to be
a bit too complicated for the very small potential benefit. Nevertheless,
some of the changes below are the results of this attempt; I kept them
because they are useful in their own right.
Change the code for traversing the procedures of a predicate
to be more direct.
Put the access predicates in the poly_info type in the same order
as the fields they operate on.
compiler/error_util.m:
Allow recording that an error is discovered during the polymorphism pass.
compiler/mercury_compile_front_end.m:
If polymorphism finds errors, print their messages, and then stop;
don't continue to the later passes.
compiler/maybe_error.m:
New module, containing the maybeN types (taken from prog_io_utio.m)
and the safe_to_continue type (taken from modes.m). These are now
needed by polymorphism.m as well.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Mention the new module.
compiler/options.m:
doc/user_guide.texi:
Delete the (undocumented, developer-only) --no-polymorphism option,
since its use cannot lead to anything other than a compiler abort,
and this won't change in the future.
compiler/hlds_pred.m:
Rename the "marker" type to "pred_marker", to clarify its purpose.
Rename the "attribute" type to "pred_attribute", for the same reason.
Make the pred_markers and attributes types true sets, not lists
masquerading as sets.
Add a predicate to add more than one marker at a time to a set of markers.
Delete an unused predicate.
Rename the functors of the can_process type to clarify its purpose.
(I tried to use it to record the presence of errors discovered by
polymorphism.m, and this did not work; these renames should spare
others a similar experience.)
Make the code that construct pred_infos build its components from first
field to last field, not in random order.
compiler/det_analysis.m:
Specialize an exported predicate to its actual uses.
compiler/hlds_out_pred.m:
Dump the cannot_process_yet flag for procedures that have them.
compiler/add_pragma.m:
compiler/add_pred.m:
compiler/complexity.m:
compiler/deforest.m:
compiler/equiv_type_hlds.m:
compiler/field_access.m:
compiler/goal_expr_to_goal.m:
compiler/higher_order.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/lambda.m:
compiler/ml_accurate_gc.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/prog_io.m:
compiler/prog_io_dcg.m:
compiler/prog_io_goal.m:
compiler/prog_io_item.m:
compiler/prog_io_mode_defn.m:
compiler/prog_io_mutable.m:
compiler/prog_io_pragma.m:
compiler/prog_io_sym_name.m:
compiler/prog_io_type_defn.m:
compiler/prog_io_typeclass.m:
compiler/prog_io_util.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/simplify_goal_unify.m:
compiler/ssdebug.m:
compiler/stm_expand.m:
compiler/superhomogeneous.m:
compiler/table_gen.m:
compiler/try_expand.m:
compiler/unify_proc.m:
Conform to the changes above.
tests/invalid/higher_order_no_detism.{m,err_exp}:
A new test case to test that the compiler does not abort, but generates
an error message when it sees a curried predicate call to a predicate with
no declared determinism.
tests/invalid/Mmakefile:
Enable the new test case.
|
||
|
|
bbb2535eb5 |
Break up mercury_to_mercury.m.
With almost 6000 lines, mercury_to_mercury.m was one of the biggest modules
of compiler, but it was far from cohesive. This diff carves seven new modules
out of it, each of which is much more cohesive. The stuff remaining in
mercury_to_mercury.m is still not as cohesive as one would like, but it is
now small enough that moving its individually-cohesive parts into modules
of their own would be overkill.
Three consequences of the old mercury_to_mercury.m's lack of cohesion
were that
- the order of predicate declarations often did not match the order of
their implementation;
- related predicates were not grouped together;
- even when they were grouped together, the order of those groups
was often random.
This diff fixes all three of these problems for all eight successor modules
of mercury_to_mercury.m: the seven new modules, and the new
mercury_to_mercury.m itself.
In some cases, this diff adds or improves the documentation of the predicates
in mercury_to_mercury.m's successor modules. In some other cases, it just
documents the lack of documentation :-(. In yet other cases, it removes
"documentation" that says nothing that isn't obvious from the predicate's name.
There are some algorithmic changes, but they are all trivial.
compiler/parse_tree_out.m:
New module containing the code to print out the top levels of parse trees,
including most sorts of items.
compiler/parse_tree_out_clause.m:
New module containing the code to print out clauses and goals.
compiler/parse_tree_out_pragma.m:
New module containing the code to print out pragmas.
compiler/parse_tree_out_pred_decl.m:
New module containing the code to print out predicate, function and
mode declarations. It is separate from parse_tree_out.m because a
significant number of compiler modules need only its functionality,
and not parse_tree_out.m's functionality.
compiler/parse_tree_out_inst.m:
New module containing the code to print out insts and modes.
compiler/parse_tree_out_term.m:
New module containing the code to print out variables and terms.
compiler/parse_tree_out_info.m:
New module containing the infrastructure of both mercury_to_mercury.m
and the other new modules.
compiler/parse_tree.m:
Include the new modules.
compiler/notes/compiler_design.html:
Document the new modules.
compiler/Mercury.options:
Transfer an option from mercury_to_mercury.m to the successor module
that needs it.
compiler/*.m:
Import one of the new modules either as well as, or instead of,
mercury_to_mercury.m. In most cases, we need to import only one
or two of mercury_to_mercury.m's successor modules; nowhere do we
need to import all eight.
Clean up some code in termination.m around a call to one of the
new modules.
tools/speedtest:
Replace mercury_to_mercury.m on the list of the ten largest modules
of the compiler.
|
||
|
|
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.
|
||
|
|
1aee1b8ade |
Don't put variable names in clauses in .opt files.
After this diff, a change in the source file that affects only variable names
won't cause the recompilation of the other modules that use the changed
module's .opt file. (I got a bunch of such unnecessary recompilations when
giving new names to many of varset.m's variables.)
compiler/prog_data.m:
Add a new type named var_name_print to replace the boolean that used
to specify whether we wanted to print the variable number as a suffix
after the variable name. This new type allows us to specify not just that
e.g. a variable numbered 10 and named Example should be printed as
Example or as Example_10, but also as V_10.
compiler/intermod.m:
Use this capability to print variables in only the V_N form when
putting clauses in .opt files. After this diff, a change in the source
file that affects only variable names won't cause the recompilation
of the other modules that use the change module's .opt file.
Convert (C->T;E) into (if C then T else E).
compiler/mercury_to_mercury.m:
compiler/hlds_out_goal.m:
compiler/hlds_out_mode.m:
compiler/hlds_out_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
Generalize mercury_var_to_string, and the predicates that call it
directly or indirectly, to take an argument of the var_name_print type
instead of the old AppendVarNum boolean.
Put the argument lists of the affected predicates in a better order,
with related parameters being next to each other, and moving more global
parameters before more local parameters.
Add versions of mercury_var_to_string to mercury_vars_to_string
that assume the print_name_only value for the var_name_print parameter,
since this is typically what we want when we generate error messages.
In hlds_out_pred.m, add another type, write_which_modes, to replace
another boolean parameter.
compiler/add_foreign_proc.m:
compiler/add_pragma_type_spec.m:
compiler/check_typeclass.m:
compiler/code_loc_dep.m:
compiler/dep_par_conj.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/field_access.m:
compiler/format_call.m:
compiler/goal_expr_to_goal.m:
compiler/hlds_desc.m:
compiler/layout_out.m:
compiler/liveness.m:
compiler/llds_out_instr.m:
compiler/make_hlds_warn.m:
compiler/mercury_to_mercury.m:
compiler/mode_debug.m:
compiler/mode_errors.m:
compiler/pd_debug.m:
compiler/post_typecheck.m:
compiler/prog_ctgc.m:
compiler/prog_io_item.m:
compiler/prog_io_mutable.m:
compiler/prog_io_type_defn.m:
compiler/prog_io_typeclass.m:
compiler/prog_util.m:
compiler/purity.m:
compiler/push_goals_together.m:
compiler/rbmm.live_variable_analysis.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/saved_vars.m:
compiler/stack_opt.m:
compiler/structure_reuse.indirect.m:
compiler/type_assign.m:
compiler/type_constraints.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/unneeded_code.m:
compiler/unused_args.m:
Conform to the above changes.
|
||
|
|
cbc6268c67 |
Print precise contexts for duplicate field names.
compiler/add_type.m:
Record the context of the field name, not the context of the data
constructor as a whole. The more fields a constructor has, and the
more extensive comments they each have, the more misleading the
overall context will be. (The code that uses these contexts does not
need changing.)
compiler/prog_data.m:
To store the information that add_type.m needs, create a space for
the context of each field name next to the name itself. This requires
breaking an old type equivalence; most of the "conform" changes below
result from this.
compiler/prog_io_type_defn.m:
When parsing type definitions, record the context of each field name
in the new space.
compiler/field_access.m:
compiler/hlds_data.m:
compiler/hlds_pred.m:
compiler/make_hlds_passes.m:
compiler/mercury_to_mercury.m:
compiler/ml_code_util.m:
compiler/prog_type.m:
compiler/recompilation.check.m:
compiler/type_ctor_info.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/xml_documentation.m:
Conform to the changes above.
compiler/post_typecheck.m:
Conform to the changes above.
Move some code out of a loop.
Give a predicate a more meaningful name.
tests/invalid/repeated_field_name.{m,err_exp}:
A new test case for this change, which defines a field named f2
three times. Before this change, the compiler reported:
repeated_field_name.m:008: Error: field `repeated_field_name.f2' multiply
repeated_field_name.m:008: defined.
repeated_field_name.m:008: Here is the previous definition of field
repeated_field_name.m:008: `repeated_field_name.f2'.
which is a bit baffling. We now report
repeated_field_name.m:011: Error: field `repeated_field_name.f2' multiply
repeated_field_name.m:011: defined.
repeated_field_name.m:010: Here is the previous definition of field
repeated_field_name.m:010: `repeated_field_name.f2'.
repeated_field_name.m:012: Error: field `repeated_field_name.f2' multiply
repeated_field_name.m:012: defined.
repeated_field_name.m:010: Here is the previous definition of field
repeated_field_name.m:010: `repeated_field_name.f2'.
which gives the correct contexts, and also reports BOTH duplicates.
(Previously, we generated two identical error messages, but then sorting
the list of errors removed one of them.)
tests/invalid/Mmakefile:
Enable the new test case.
|
||
|
|
01390ef861 |
Make is_exist_constr a proper type, not a synonym for boolean.
compiler/hlds_goal.m:
The is_exist_constr field of rhs_functor, which used to be represented by
a synonym of boolean. Make this type an enum type.
compiler/*.m:
Conform to the above change.
|
||
|
|
3ce91ecae0 |
When converting a from_ground_term_initial scope to a from_ground_term_other
Estimated hours taken: 24 Branches: main When converting a from_ground_term_initial scope to a from_ground_term_other scope because after a program transformation, some part of it no longer meets the invariants required for from_ground_term_initial scopes, put from_ground_term_initial scopes around any PART of the original scope that still preserves those invariants. This can give a significant speedup, since such scopes have MANY more optimizations than from_ground_term_other scopes. Do the same when a from_ground_term_construct scope is converted to a from_ground_term_other scope. compiler/purity.m: compiler/polymorphism.m: Both these modules contain code that can convert a from_ground_term scope from initial or construct to other. Change the code that does the conversion to do what the comment at the top says. (The transformation in purity.m is part of the post typecheck phase, which may discover that what looks like a unification is actually a call to an evaluable function; the transformation in polymorphism.m may discover the need for the insertion of code constructing or retrieving type_infos.) In both modules, take advantage of the fact that fgt scopes contain conjunctions of var-functor unifications to optimize the code a bit. In purity.m, change the interface of some predicates to make it clear that they do not update the purity_info. compiler/from_ground_term_util.m: A new module containing the part of the optimized conversion process that is independent of the program transformation that triggers the conversion. compiler/hlds.m: Add the new module to this package. compiler/notes/compiler_design.html: Describe the new module. compiler/post_typecheck.m: Change the order of some arguments to match the rest of the compiler. |
||
|
|
62cf56032e |
Make the compiler able to compile the zm_rcpsp_cpx.m stress test.
Estimated hours taken: 24 Branches: main Make the compiler able to compile the zm_rcpsp_cpx.m stress test. There were two problems. First, compilers compiled in hlc.gc ran out stack before they even started semantic analysis. Second, compilers compiled in asm_fast.gc ran into horrible worst case behavior in the mode checker. The reason for that was this line of code: T0_ArrayList = zb_cii1d_array([bc(no), bc(no), bc(no), ... ... ...]) The zb_cii1d_array is a function call, which is why the scope is not subject to all the special handling I implemented last year. That was one performance problem. The other was the fact that all the list elements (of which there are LOTS; that line of code has more than 68,000 columns) are either bc(no) or bc(yes). This means that the insts of the variables representing the various partial lists very similar, which makes equality tests among them (such as those required for tests of set membership) fail only after doing lots of work. The changes also make the compiler about 1.5% faster on tools/speedtest. compiler/modecheck_unify.m: Fix the main problem with that stress test, which was the VERY expensive but redundant update of the insts of the Ys in unifications of the form X = f(Y1, ..., Yn) when X is initially free. We already avoided such redundant updates inside from_ground_term_construct scopes, but in this stress test, that scope gets converted into a from_ground_term_other scope due to the presence of a function call inside it. A much more minor optimization is to push some code into one branch of an if-then-else. compiler/modecheck_util.m: The REASON why the above redundant call is so expensive is because for large insts, it is very expensive to abstractly unify an inst with itself. We therefore now check if two insts being unified are the same. This should prevent bad worst-case behavior of abstract inst unification even when called from contexts other than the one in modecheck_unify. compiler/modecheck_conj.m: Inline the modecheck_conj_list_schedule predicate inside the modecheck_conj_list_flatten_and_schedule predicate. This allows the modechecking of conjunctions to be tracked in the debugger much more easily, because the direct recursion of modecheck_conj_list_flatten_and_schedule allows the debugger to collapse all the recursive calls, something it cannot do for the mutual recursion of the original two predicates. compiler/superhomogeneous.m: Instead of having predicates return num_added_goals results that their callers have to add up, thread an num_added_goals state variable through those predicates. By avoiding the final addition, we can make several calls tail calls that weren't tail calls before. This allows the superhomogeneous transformation to handle significantly larger terms than before without running of stack space. Make the predicates that insert and append argument unifications work in less stack space by handling the first three arguments of each functor WITHOUT looping over them. Make the predicates that insert and append argument unifications work faster by avoiding the construction of a list for the arguments that have been tested for state variable expansion (the replacement of e.g. !.X and !:X); instead, we now test each argument just before processing it ourselves. Avoid unnecessary checking of the conjunctions created for the unifications of functor arguments for being hooks for state variable renames; since they are not branches in branched goals, they can never be such hooks. Give some predicates better names. compiler/field_access.m: For efficient interoperation with superhomogeneous.m, thread num_added_goals variables through. compiler/add_clause.m: compiler/goal_expr_to_goal.m: Conform to the changes above. compiler/prog_data.m: Make the rename_vars_in_term predicate work in less stack space by renaming the first three arguments of each functor WITHOUT looping over them. compiler/mlds_to_il.m: compiler/saved_vars.m: Rename two predicates to avoid ambiguity. compiler/polymorphism.m: Avoid printing progress messages that generate clutter unless asked for. compiler/modecheck_goal.m: Simplify some code. compiler/purity.m: Fix a comment. |
||
|
|
295415090e |
Convert almost all remaining modules in the compiler to use
Estimated hours taken: 6 Branches: main compiler/*.m: Convert almost all remaining modules in the compiler to use "$module, $pred" instead of "this_file" in error messages. In a few cases, the old error message was misleading, since it contained an incorrect, out-of-date or cut-and-pasted predicate name. tests/invalid/unresolved_overloading.err_exp: Update an expected output containing an updated error message. |
||
|
|
012962fd17 |
Change the argument order of predicates in the varset module to make
Branches: main Change the argument order of predicates in the varset module to make them more conducive to the use of state variable notation. library/varset.m: As above. library/parser.m: library/term_io.m: library/svvarset.m: compiler/*.m: samples/interpreter.m: tests/debugger/interpreter.m: tests/general/interpreter.m: tests/hard_coded/bigtest.m: tests/hard_coded/deep_copy_bug.m: tests/hard_coded/lp.m: tests/hard_coded/pprint_test.m: tests/hard_coded/type_spec_ho_term.m: Conform to the above change and remove dependencies on the svvarset module. |
||
|
|
b3fa535100 |
A rewrite of the state variable transformation from the ground up.
Estimated hours taken: 60
Branches: main
A rewrite of the state variable transformation from the ground up.
The initial aim was to avoid situations (encountered in the g12 project)
in which the old state variable transformation generated code that
did not satisfy the mode checker, due to unnecessary unifications.
The new system tries hard to minimize the number of unifications added to the
program. It does this by relying extensively on the idea that in a branched
structure such as an disjunction, if two branches both update the same state
variable, and the variables representing the last state of the state variable
in the two branches are (say) X and Y, and we pick X to represent the current
state after the disjunction, then we don't have to put the assignment X := Y
into the second branch; instead, we can RENAME Y to X in that branch.
To avoid renaming a goal several times (for itself, for its parent, for its
grandparent etc), we delay all renamings until the end, when we do it all
in one traversal.
The old state var system was opaque and hard to understand, partly because
its basic operations did different things in different contexts. The new system
is a much more direct expression of the intuitive meaning of state variables;
it keeps track of their state much as the programmer writing the original code
would. It should therefore be significantly easier to understand and to modify
in the future.
The new system can also detect more kinds of errors in the use of state
variables. For example it can discover that some branches of a disjunction or
if-then-else set the initial value of a state variable and some do not.
This is ok if the non-setting-branch cannot succeed; if it can, then it is
a bug. We therefore generate messages about such branches, but print them
only if mode analysis finds a bug in the procedure, since in that case,
the lack of initialization may be the cause of the bug.
doc/reference_manual.texi:
Replaced an old example that didn't know what it was talking about,
and thoroughly confused the issue of what is legal use of state
variables and what is not.
compiler/state_var.m:
Rewrite this module along the lines mentioned above.
compiler/options.m:
Add two new options. One, warn-state-var-shadowing, controls whether
we generate warnings for one state var shadowing another (which
G12 has lots of). The other, --allow-defn-for-builtins, is for
developers only; it is needed to bootstrap changes that add new
builtins. I needed this for a form of the state variable transformation
that used calls to a new builtin predicate to copy the values of state
variables in branches that did not modify them, even though other
branches did. I ultimately used unifications to do this copying,
for reasons documented in state_var.m.
compiler/add_clause.m:
compiler/add_pragma.m:
Respect the new --allow-defn-for-builtins option.
(Previously, we changed the code that now looks up the value of the
option.)
doc/user_guide.texi:
Document the --warn-state-var-shadowing option.
Fix some old documentation about dump options.
compiler/simplify.m:
Fix an old oversight: list the predicates in table_builtin.m that may
have calls introduced to them by table_gen.m.
compiler/superhomogeneous.m:
compiler/field_access.m:
compiler/add_clause.m:
compiler/goal_expr_to_goal.m:
Together with state_var.m, these modules contain the transformation
from the parse tree to the HLDS. Since the change to state_var.m
involves significant changes in its interface (such as separating out
the persistent and location-dependent aspects of the information needed
by the state variable transformation), and needing callbacks at
different points than the old transformation, these modules had to
change extensively as well to conform.
goal_expr_to_goal.m is a new module carved out of add_clause.m.
It deserves a module of its own because its code has a significantly
different purpose than add_clause.m. The two separate modules each
have much better cohesion than the old conjoined module did.
In superhomogeneous.m, replace two predicates that did the same thing
with one predicate.
compiler/make_hlds.m:
compiler/notes/compiler_design.html.m:
Mention the new module.
compiler/hlds_goal.m:
Add a mechanism to do the kind of incremental renaming that the state
variable transformation needs.
Add some utility predicates needed by the new code in other modules.
compiler/hlds_clause.m:
compiler/hlds_pred.m:
Add an extra piece of information to clauses and proc_infos:
a list of informational messages generated by the state variable
transformation about some branches of branched goals not giving initial
values to some state variables, while other branches do.
The state variable transformation fills in this field in clauses
where relevant.
compiler/clause_to_proc.m:
Copy this list of messages from clauses to proc_infos.
compiler/modes.m:
When generating an error message for a procedure, include this list
of messages from the state var transformation in the output.
compiler/handle_options.m:
Add a dump alias for debugging the state var transformation.
compiler/hlds_out_goal.m:
Add a predicate that is useful in trace messages when debugging
the compiler.
compiler/hlds_out_pred.m:
Print goal path and goal id information in clauses as well as
proc_infos, since the state var transformation now uses goal ids.
compiler/prog_item.m:
In lists of quantified vars in scope headers, separate out the vars
introduced as !S from those introduced as !.S and !:S. This makes it
easier for the state var transformation to handle them.
Document that we expect lists of quantified variables and state
variables to contain no duplicates. The state var transformation
is slightly simpler if we impose this requirement, and quantifying
a variable twice in the same scope does not make sense, and is
therefore almost certainly an error.
compiler/prog_io_util.m:
Generate error messages when a variable or state variable IS
listed twice in the same quantification list.
Factor out some code used to generate error messages.
compiler/typecheck.m:
Conform to the changes above.
Break a very large predicate into two smaller pieces.
compiler/add_class.m:
compiler/add_pragma.m:
compiler/add_pred.m:
compiler/assertion.m:
compiler/dead_proc_elim.m:
compiler/dependency_graph.m:
compiler/goal_path.m:
compiler/goal_util.m:
compiler/headvar_names.m:
compiler/hhf.m:
compiler/hlds_out_module.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/mercury_to_mercury.m:
compiler/module_imports.m:
compiler/module_qual.m:
compiler/post_typecheck.m:
compiler/prog_io_goal.m:
compiler/prog_util.m:
compiler/purity.m:
compiler/unify_proc.m:
compiler/unused_imports.m:
Conform to the changes above.
compiler/mode_constraints.m:
compiler/modules.m:
compiler/structure_reuse.analysis.m:
Avoid the warnings we now generate about one state variable shadowing
another.
browser/declarative_user.m:
compiler/hlds_out_util.m:
compiler/ordering_mode_constraints.m:
compiler/table_gen.m:
deep_profiler/read_profile.m:
Improve programming style.
library/require.m:
Add expect_not, a negated version of expect.
library/varset.m:
Return lists of new variables in order, not reverse order.
mdbcomp/mdbcomp.goal_path.m:
compiler/prog_mode.m:
Add a utility predicate.
tests/debugger/tailrec1.exp:
tests/invalid/any_passed_as_ground.err_exp:
tests/invalid/bad_sv_unify_msg.err_exp:
tests/invalid/state_vars_test1.err_exp:
tests/invalid/state_vars_test4.err_exp:
tests/invalid/try_bad_params.err_exp:
tests/invalid/try_detism.err_exp:
tests/invalid/purity/impure_pred_t1_fixed.err_exp:
tests/invalid/purity/impure_pred_t2.err_exp:
Update the expected outputs of these test cases to account for
incidental changes in variable numbers and goal paths after this
change.
tests/general/state_vars_tests.{m,exp}:
Remove the code that expected the state var transformation to do
something that was actually AGAINST the reference manual: treating
the step from the condition to the then part of an if-then-else
expression (not a goal) as a sequence point.
tests/general/state_vars_trace.m:
Add a test case that is not enabled yet, since we don't pass it.
tests/hard_coded/bit_buffer_test.m:
Fix a bug in the test itself: the introduction of a state var twice
in the same scope.
tests/hard_coded/try_syntax_6.m:
Avoid a warning about state var shadowing.
tests/hard_coded/if_then_else_expr_state_var.{m,exp}:
A new test to check the proper handling of state vars in if-then-else
expressions.
tests/hard_coded/Mmakefile:
Enable the new test.
|
||
|
|
8a28e40c9b |
Add the predicates sorry, unexpected and expect to library/error.m.
Estimated hours taken: 2 Branches: main Add the predicates sorry, unexpected and expect to library/error.m. compiler/compiler_util.m: library/error.m: Move the predicates sorry, unexpected and expect from compiler_util to error. Put the predicates in error.m into the same order as their declarations. compiler/*.m: Change imports as needed. compiler/lp.m: compiler/lp_rational.m: Change imports as needed, and some minor cleanups. deep_profiler/*.m: Switch to using the new library predicates, instead of calling error directly. Some other minor cleanups. NEWS: Mention the new predicates in the standard library. |
||
|
|
77a6a6c10c |
Implement several more changes that together speed up compilation time
Estimated hours taken: 16 Branches: main Implement several more changes that together speed up compilation time on training_cars_full by 12%, and also improve tools/speedtest -h by 7.2% and tools/speedtest by 1.6%. The first change is designed to eliminate the time that the compiler spends constructing error messages that are then ignored. The working predicates of prog_io_sym_name used to always return a single result, which either gave a description of the thing being looked, or an error message. However, in many places, the caller did not consider not finding the thing being looked for to be an error, and thus threw away the error message, keeping only the "not found" indication. For each predicate with such callers, this diff provides a parallel predicate that indicates "not found" simply by failing. This allows us to eliminate the construction of the error message, the preparation for the construction of the error message (usually by describing the context), and the construction of the "ok" wrapper. The second change is to specialize the handling of from_ground_term_construct scopes in the termination analyzer. To make this easier, I also cleaned up of the infrastructure of the termination analyzer. The third change is to avoid traversing from_ground_term_construct scopes in quantification.m when finding the variables in a goal, since termination analysis no longer needs the information it gathers. The fourth change is to avoid traversing second and later conjuncts in conjunctions twice. The first step in handling conjunctions is to call implicitly_quantify_conj, which builds up a data structure that pairs each conjunct with the variables that occur free in all the conjuncts following it. However, after this was done and each conjunct was annotated with its nonlocals, we used to compute the variables that occur free in the conjunction as a whole from scratch. This diff changes the code so that we now compute that set based on the information we gathered earlier, avoiding a redundant traversal. The fifth change is to create specialized, lower-arity versions of many of the predicates in quantification.m. These versions are intended for traversals that take place after the compiler has replaced lambda expressions with references to separate procedures. These traversals do not need to pass around arguments representing the variables occurring free in the (now non-existent) lambda expressions. compiler/prog_io_sym_name.m: Make the first change described above. Change some predicate names to adopt a consistent naming scheme in which predicates that do the same job and differ only in how they handle errors have names that differ only in a "try_" prefix. Add some predicate versions that do common tests on the output of the base versions. For example, try_parse_sym_name_and_no_args is a version of try_parse_sym_name_and_args that insists on finding an empty argument list. Remove the unused "error term" argument that we used to need a while ago. Move some predicate definitions to make their order match the order of their declarations. Turn a predicate into a function for its caller's convenience. compiler/term_constr_build.m: Make the second change described above by modeling each from_ground_term_construct scope as a single unification, assigning the total size of the ground term to the variable being built. compiler/term_constr_util.m: Put the arguments of some predicates into a more standard order. compiler/lp_rational.m: Change the names of some function symbols to avoid both the use of graphic characters that require quoting and clashes with other types. Change the names of some predicates to make their purpose clear, and to avoid ambiguity. compiler/quantification.m: Make the third, fourth and fifth changes described above. compiler/*.m: Conform to the changes above. |
||
|
|
cc9423e35d |
Rationalize the way the MLDS code generator handles global data structures.
Estimated hours taken: 80
Branches: main
Rationalize the way the MLDS code generator handles global data structures.
The previous way was somewhat perverse in several respects.
The first respect was that static Mercury terms were translated into global
MLDS definitions, those MLDS definitions were turned into local definitions,
and then later turned back into global definitions. However, while they were
local definitions, they were part of the list of definitions processed
by ml_elim_nested. Since the complexity of ml_elim_nested is at least O(n^2)
and probably O(n^3) or worse, and since the definitions representing static
terms could increase the value of n from dozens or hundred to many thousands,
this was a BAD IDEA, especially since by construction, the MLDS definitions
representing ground terms cannot have other definitions nested inside them.
This problem was the main reason why previously the compiler took effectively
forever to compile any program with large tables of facts in MLDS grades.
The second respect has to do with the fact that terms are represented as tagged
pointers to memory cells. When generating an MLDS definition (a static cell)
for a ground term, ml_unify_gen.m remembered the name of the MLDS variable
representing the static cell, but forgot the tag on the pointer. So when
that ground term was used as an argument in another, bigger ground term,
it had to figure out the tag all over again. The argument of the
construct_statically functor in construct unifications had as its sole purpose
the provision of the data needed by this recomputation.
The third respect was that the code generator could generate duplicate
definitions (same variable name, same content) when two conjoined goals
referred to two or more type_infos or pseudo_type_infos for the same type.
The code generator used to handle it by wrapping a scope around the later
definitions, which (a) wasted memory, and (b) could yield warnings from
the C compiler about shadowed declarations. This problem used to prevent
the compiler from bootchecking in grade hlc_nest.gc; with this diff,
we can again bootcheck in grade hlc_nest.gc.
The fourth respect was that the code generator's record of which variables are
bound to constant terms was inaccurate, because it was never reset. If a
variable was bound to a constant term in one branch of a control structure,
the MLDS code generator state's record of this binding was still there
when the compiler generated code for the later branches of that control
structure. It did not use the record, but it was still there.
The MLDS code generator also used a horribly inefficient algorithm for figuring
out which Mercury variables should have their corresponding MLDS variables
declared at a given goal. It gathered up all the goals's variables, and then
gathered up all the variables in the goal's immediate subgoals. This meant
that the entire goal had to be traversed TWICE, with the second traversal
being needed only because the first one gathered too much information.
Those traversals were a huge performance problem on programs with large static
terms, since their representation is large conjunctions of unifications,
which have large numbers of variables. To add insult to injury, the traversals
used ordered lists to represent the sets, which meant that (given the ascending
variable numbers in from_ground_term scopes), adding the n'th unification's
new variable to the set took O(n) time, with the complexity of the whole
algorithm being quadratic.
Besides fixing these problems, this diff makes the MLDS code generator
handle from_ground_term_construct scopes specially, in a streamlined fashion,
just as the LLDS backend has done for a while now. It also fixes a bunch
of other performance problems pointed out by profiling.
This diff reduces the compilation time on the training_cars_150.m benchmark,
which has nothing but ground terms, from 94+ seconds to less than 2 seconds,
a 98% speedup. (This is with from_ground_term scopes enabled, as is
appropriate.) For ordinary programs, compilation time in grade hlc.gc
is reduced by about 3%.
compiler/ml_global_data.m:
A new module that manages the MLDS code generator's records about
static definitions. It separates those definitions into different
categories based on what kind of processing they need. At the moment,
the categories are: definitions of cells for ground terms and
definitions of cells for RTTI, with the latter being subdivided
into those that may need to be processed by ml_elim_nested
and those that are known not to need such processing.
It also records whether we have generated representation for a
type_info or pseudo_type yet, so that we can avoid generating duplicate
definitions. This, and the code that uses this, fixes the third
problem.
compiler/ml_backend.m:
compiler/notes/compiler_design.html:
Add the new module.
compiler/goal_util.m:
Add a warning about the bad complexity of goal_vars.
compiler/hlds_goal.m:
Remove the static_cons type, since it is no longer needed.
Remove the static_cons argument of the construct_statically
functor of the how_to_construct type.
Fix an out-of-date comment about from_ground_term scopes.
compiler/mark_static_terms.m:
Change the data structure being threaded through this module
from being a map(prog_var, static_cons) to a set_tree234(prog_var),
since we no longer need the information stored in static_conses.
compiler/modes.m:
Do not compute static_conses.
compiler/mlds.m:
Put the information about global data into a separate field of
the MLDS, since some classes of such data can have their treatment
optimized.
Put the arguments of some functions into a more logical order.
Give some function symbol names prefixes to avoid ambiguities.
Change or add some field name prefixes to avoid ambiguities.
Avoid the unnecessary use of higher order code in handling the flags of
MLDS definitions. The new code is simpler as well as faster than the
old.
compiler/ml_code_util.m:
Make ml_global_data a part of the MLDS code generator state. This
allows a bunch of predicates in the MLDS code generator to no longer
return lists of definitions, since those definitions are now put
into this new part of ml_gen_info, which ml_elim_nested won't touch.
This is part of the solution of the first problem.
Replace the field that mapped vars to the name of the global static
definition involved in representing the ground term bound to that var
with a field that maps the var to the actual rval (which will be a
tagged pointer to that static definition), though we also remember
the variable's type, since this is needed for making decisions about
boxing. This is part of the solution for the second problem.
Rename the extra_defns field of the ml_gen_info to the
closure_wrapper_defns field, since this is the only thing that
it is used for.
Add fields to the ml_gen_info holding the value of the --highlevel-data
option and the compilation target, since these are needed very often,
and looking them up in the globals is too slow.
Access all fields of ml_gen_info via access predicates, not via field
notation, so that the number of accesses to each field can be measured
by deep profiling.
Separate the ml_gen_info structure into a main structure whose fields
are frequently updated and which fits into an 8-word block of memory,
and a substructure whose fields are read-only or rarely updated.
This should help improve memory performance.
Provide more useful access predicates to some of the counters,
and make them harder to confuse by using fewer type synonyms.
Provide some more convenient predicates for creating auxiliary MLDS
variables (those that do not correspond to Mercury variables).
Delete ml_join_decls, since fixing the third problem means that it is
no longer needed.
Delete some other predicates whose job has been taken over by
ml_global_data.m.
Put the arguments of some predicates into a more logical order.
Rename some predicates to avoid ambiguities.
compiler/ml_code_gen.m:
As part of the fix for the repeated traversals of parts of the
procedure body with goal_vars, we now have to run quantification
before generating MLDS for a procedure. Quantification does in
one optimized pass what the old code used to do in many unoptimized
passes. However, since quantification can change the HLDS, this
requires a small change in the module's interface. HLDS dump 499
now dumps to the HLDS version *output* by MLDS code generation,
not the HLDS version that is its input.
Use the (now guaranteed accurate) nonlocals fields of the goal and
its immediate subgoals to figure out what variables need to declared at
each goal. This fixes the fifth problem.
Special case from_ground_term_construct scopes. (This code recognizes
such scopes; the code that handles them is in ml_unify_gen.m.)
Use trace goals to print progress messages.
Avoid the use of io.format and string.format (see below).
Group the predicates of this module a bit more meaningfully.
(A really good order requires more reordering, but that will be
a separate change.)
Give some predicates more meaningful names.
Add predicates that allow the convenient implementation of branched
control structures.
Use them in the implementation of the branched control structures
handled in this module
Together, these solve the fourth problem.
compiler/ml_switch_gen.m:
compiler/ml_string_switch.m:
Use them in the implementation of the branched control structures
handled in these modules.
Use the new module to generate constant data.
compiler/ml_unify_gen.m:
Implement the changes described at the top.
Divide ml_gen_new_object, a predicate that used to be 220 lines long,
into several pieces, one for each different method of constructing new
objects (memory cells).
Delete the (extensive) code that used to recreate the tags on
pointers to static cells. This code used to also recreate static
arguments in their entirety if they were NOT pointers to cells,
e.g. if they were integers or floats or strings, so we now record
the values of such non-tagged-pointer constant terms also.
Put the arguments of some predicates into a more logical order.
In addition, some predicates now need ml_global_data threaded through
them, but avoid returning lists of definitions.
compiler/ml_call_gen.m:
Simplify the interface of the predicate that decides on boxing and
unboxing, making it callable from places that do not have a full code
generator state (such as the streamlined code in ml_unify_gen handling
from_ground_term_construct scopes).
Avoid the unnecessary use of higher order code.
Rename a predicate to avoid ambiguity.
compiler/ml_closure_gen.m;
Generate the closure layout information as static global data.
compiler/ml_elim_nested.m:
Thread the globals through this module instead of the I/O state,
since the only thing the I/O state was used for was accessing the
globals.
Traverse only the small subset of global data that needs to be
traversed.
compiler/ml_type_gen.m:
Use trace goals to print progress messages.
Replace a semidet predicate with a function returning a tailored type,
for improved robustness.
Look up stuff in the globals structure less frequently, by reusing the
results of past lookups.
compiler/rtti_to_mlds.m:
Restructure the code in this module in two respects.
First, instead of having predicates returning lists of
MLDS definitions, make them add those definitions to a ml_global_data
data structure threaded through the module. Since the ml_global_data
structure records which type_infos and pseudo_type_infos we have
already generated definitions for, this allows us to avoid generating
duplicate static cells for them. This allows us to avoid the old
code's roundabout way of handling of such cells.
Second, several predicates of this module returned initializers,
which their caller then stuck into a static definition. This diff
changes things so that wherever possible, the predicate that computes
the initializers also creates the cell definition. This improves the
code's cohesion.
Also, rename some predicates where, after the above changes, their old
names are no longer appropriate.
compiler/mlds_to_c.m:
Avoid the use of io.format and string.format, since (after the more
extensive changes described at the top of this log message) this
turned out to account for a nontrivial percentage of the compiler's
runtime.
Instead of repeatedly looking up the values of some options
in a copy of the globals obtained from the I/O state, thread
through this module a term that records all the information
that this module needs from globals.
Threading this data through this module instead of looking something
upo in the I/O state leads to a slight slowdown, but not having to do
option lookups in large trees leads to a larger speedup.
Rename some predicates to ambiguity.
Convert some predicate definitions from multiple clauses into one,
for clarity.
Conform to the changes in the structure of the MLDS.
compiler/mlds_to_gcc.m:
Conform to the changes in the structure of the MLDS.
compiler/mlds_to_il.m:
compiler/mlds_to_ilasm.m:
compiler/mlds_to_java.m:
compiler/mlds_to_managed.m:
Conform to the changes in the structure of the MLDS.
Pass the globals to this module instead of looking it up in the
I/O state.
Rename some predicates to ambiguity.
Avoid the unnecessary use of higher order code.
In mlds_to_managed.m, thread a previously frequently-looked-up value
through the module.
compiler/typecheck_info.m:
The code for expanding equivalence types in a procedure's vartypes
field used to iterate on the keys of the vartypes map, and then
looked up the associated values in the map. This diff replaces hat
with new code that iterates on an association list that puts the
value right next to its key (a list that the old code just threw away).
The var/type assoc list we compute is still sorted on the variables,
so create the new vartypes map not by repeated insertion, but
directly (using map.from_sorted_assoc_list).
compiler/purity.m:
Add a note about a possible future speedup.
compiler/prog_io_sym_name.m:
Rename a predicate to avoid an ambiguity, and to make its purpose
clearer.
compiler/globals.m:
compiler/handle_options.m:
compiler/mlds_to_il.m:
Check whether the mmc option that specifies the IL version number is
well formed at the start of the compilation, in handle_options.m,
when all the other option values are checked if needed, rather than
when generating IL code. This way, we can generate an error message,
not a compiler abort.
The IL version number is now recorded in the globals structure.
compiler/make_hlds_warn.m:
Do not descend into from_ground_term scopes, since by construction,
they cannot contain singleton variables.
compiler/analysis.file.m:
compiler/deep_profiling..m:
compiler/field_access.m:
compiler/hlds_out.m:
compiler/interval.m:
compiler/liveness.m:
compiler/loop_inv.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/loop_inv.m:
compiler/ml_tailcall.m:
compiler/module_qual.m:
compiler/prog_ctgc.m:
compiler/prog_io_dcg.m:
compiler/prog_io_goal.m:
compiler/prog_io_pragma.m:
compiler/prog_io_typeclass.m:
compiler/prog_io_util.m:
compiler/quantification.m:
compiler/rbmm.add_rbmm_goal_infos.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/structure_reuse.indirect.m:
compiler/superhomogeneous.m:
compiler/var_locn.m:
Conform to the changes above.
compiler/unused_args.m:
Fix an ambiguous predicate name.
tests/hard_coded/float_field.{m,exp}:
Add some more test situations to this test case. These test
the handling of notag types in static terms more thoroughly
than before.
|
||
|
|
d69ba1a1f0 |
Include the type_ctor in cons_ids for user-defined types.
Estimated hours taken: 32 Branches: main Include the type_ctor in cons_ids for user-defined types. The intention is two-fold: - It prepares for a future in which we allow more than one function symbol to with the same name to be defined in a module. - It makes the HLDS code more self-contained. In many places, processing construction and deconstruction unifications required knowing which type the cons_id belongs to, but until now, code couldn't know that unless it kept track of the type of the variable unified with the cons_id. With this diff, user-defined cons_ids are represented as cons(SymName, Arity, TypeCtor) The last field is filled in during post-typecheck. After that time, any module qualification in the SymName (which may initially be partial) is redundant, since it is also available in the TypeCtor. In the future, we could make all those SymNames be just unqualified(_) at that time. We could also replace the current maps in HLDS type definitions with full cons_id keys with just name/arity keys (since the module qualifier is a given for any given type definition), we could also support partially qualified cons_ids in source code using a map from name/arity pairs to a list of all the type_ctors that have function symbols with that name/arity, instead of our current practice of inserting all possible partially module qualified version of every cons_id into a single giant table, and we could do the same thing with the field names table. This diff also separates tuples out from user-defined types, since in many respects they are different (they don't have a single type_ctor, for starters). It also separates out character constants, since they were alreay treated specially in most places, though not in some places where they *ought* to have been treated specially. Take the opportunity to give some other cons_ids better names. compiler/prog_data.m: Make the change described above, and document it. Put the implementations of the predicates declared in each part of this module next to the declarations, instead of keeping all the code until the very end (where it was usually far from their declarations). Remove three predicates with identical definitions from inst_match.m, inst_util.m and mode_constraints.m, and put the common definition in prog_data.m. library/term_io.m: Add a new predicate that is basically a reversible version of the existing function espaced_char, since the definition of char_consts needs reversibilty. compiler/post_typecheck.m: For functors of user-defined types, record their type_ctor. For tuples and char constants, record them as such. compiler/builtin_lib_types.m: compiler/parse_tree.m: compiler/notes/compiler_design.html: New module to centralize knowledge about builtin types, specially handled library types, and their function symbols. Previously, the stuff now in this module used to be in several different places, including prog_type.m and stm_expand.m, and some of it was duplicated. mdbcomp/prim_data.m: Add some predicates now needed by builtin_lib_types.m. compiler/builtin_ops.m: Factor out some duplicated code. compiler/add_type.m: Include the relevant type_ctors in the cons_ids generated in type definitions. compiler/hlds_data.m: Document an existing type better. Rename a cons_tag in sync with its corresponding cons_id. Put some declarations into logical order. compiler/hlds_out.m: Rename a misleadingly-named predicate. compiler/prog_ctgc.m: compiler/term_constr_build.m: Add XXXs for questionable existing code. compiler/add_clause.m: compiler/add_heap_ops.m: compiler/add_pragma.m: compiler/add_pred.m: compiler/add_trail_ops.m: compiler/assertion.m: compiler/bytecode_gen.m: compiler/closure_analysis.m: compiler/code_info.m: compiler/complexity.m: compiler/ctgc_selector.m: compiler/dead_proc_elim.m: compiler/deep_profiling.m: compiler/delay_partial_inst.m: compiler/dependency_graph.m: compiler/det_analysis.m: compiler/det_report.m: compiler/distance_granularity.m: compiler/erl_rtti.m: compiler/erl_unify_gen.m: compiler/export.m: compiler/field_access.m: compiler/foreign.m: compiler/format_call.m: compiler/hhf.m: compiler/higher_order.m: compiler/hlds_code_util.m: compiler/hlds_desc.m: compiler/hlds_goal.m: compiler/implementation_defined_literals.m: compiler/inst_check.m: compiler/inst_graph.m: compiler/inst_match.m: compiler/inst_util.m: compiler/instmap.m: compiler/intermod.m: compiler/interval.m: compiler/lambda.m: compiler/lco.m: compiler/make_tags.m: compiler/mercury_compile.m: compiler/mercury_to_mercury.m: compiler/middle_rec.m: compiler/ml_closure_gen.m: compiler/ml_code_gen.m: compiler/ml_code_util.m: compiler/ml_switch_gen.m: compiler/ml_type_gen.m: compiler/ml_unify_gen.m: compiler/ml_util.m: compiler/mlds_to_c.m: compiler/mlds_to_java.m: compiler/mode_constraints.m: compiler/mode_errors.m: compiler/mode_ordering.m: compiler/mode_util.m: compiler/modecheck_unify.m: compiler/modes.m: compiler/module_qual.m: compiler/polymorphism.m: compiler/prog_ctgc.m: compiler/prog_event.m: compiler/prog_io_util.m: compiler/prog_mode.m: compiler/prog_mutable.m: compiler/prog_out.m: compiler/prog_type.m: compiler/prog_util.m: compiler/purity.m: compiler/qual_info.m: compiler/rbmm.add_rbmm_goal_infos.m: compiler/rbmm.execution_path.m: compiler/rbmm.points_to_analysis.m: compiler/rbmm.region_transformation.m: compiler/recompilation.usage.m: compiler/rtti.m: compiler/rtti_out.m: compiler/rtti_to_mlds.m: compiler/simplify.m: compiler/simplify.m: compiler/special_pred.m: compiler/ssdebug.m: compiler/stack_opt.m: compiler/stm_expand.m: compiler/stratify.m: compiler/structure_reuse.direct.detect_garbagem: compiler/superhomoegenous.m: compiler/switch_detection.m: compiler/switch_gen.m: compiler/switch_util.m: compiler/table_gen.m: compiler/term_constr_build.m: compiler/term_norm.m: compiler/try_expand.m: compiler/type_constraints.m: compiler/type_ctor_info.m: compiler/type_util.m: compiler/typecheck.m: compiler/typecheck_errors.m: compiler/unify_gen.m: compiler/unify_proc.m: compiler/unify_modes.m: compiler/untupling.m: compiler/unused_imports.m: compiler/xml_documentation.m: Minor changes, mostly to ignore the type_ctor in cons_ids in places where it is not needed, take the type_ctor from the cons_id in places where it is more convenient, conform to the new names of some cons_ids, conform to the changes in hlds_out.m, and/or add now-needed imports of builtin_lib_types.m. In some places, the handling previously applied to cons/2 (which included tuples and character constants as well as user-defined function symbols) is now applied only to user-defined function symbols or to user-defined function symbols and tuples, as appropriate, with character constants being handled more like the other kinds of constants. In inst_match.m, rename a whole bunch of predicates to avoid ambiguities. In prog_util.m, remove two predicates that did almost nothing yet were far too easy to misuse. |
||
|
|
1abc2f39a0 |
Continue the breakup of the monster module prog_io.m.
Estimated hours taken: 3 Branches: main Continue the breakup of the monster module prog_io.m. compiler/prog_io.m: compiler/prog_io_mutable.m: compiler/prog_io_sym_name.m: Move the code in prog_io.m for dealing with declarations for mutables and for parsing symbol names and specifiers into two new modules. compiler/parse_tree.m: compiler/notes/compiler_design.html: Add the new modules. compiler/*.m: Import prog_io_sym_name instead of (or, in a couple of cases, as well as) prog_io. |
||
|
|
cc42c8fac5 |
Switch to using error_util to generate error message during the process of
Estimated hours taken: 40 Branches: main Switch to using error_util to generate error message during the process of converting terms to prog_items. In many predicates, we used to return error messages as a string/term pair, with the string being the error message and a term, which both provided the context and was printed after the message. We now return error indications as lists of error_specs. These include a printout of the relevant term only if this helps users understand the nature or the location of the error. To make the printouts easier to understand we print variable names in them using the applicable varsets. (The old version of the compiler used to print each error term long after it lost track of the right varset, and thus used a dummy varset that yielded error messages referring to _1, _2 etc instead of the variable names used by the programmer.) Sometimes the callers of some parse predicates prepended other strings indicating the context of the error in front of the error string. This diff changes things so that now the caller instead passes a list of format components describing the context to the predicates that construct the error_specs. In some places, simplify the code, e.g. by factoring out common code, and by inlining some auxiliary predicates (we used to need these auxiliary predicates for indexing when we executed the compiler using Prolog, but those days are long past). Mark with XXXs places where I think the error messages or their contexts could be improved, and places where the structure of the code could be improved. compiler/prog_io_util.m: Change the representation of the maybeN types to use error_spec lists. compiler/prog_io.m: compiler/prog_io_dcg.m: compiler/prog_io_goal.m: compiler/prog_io_pragma.m: compiler/prog_io_typeclass.m: compiler/prog_io_util.m: Change the way we generate error messages along the lines described at the top. In several cases, this required adding extra arguments (varsets, context descriptions) to predicates for use in error messages. Some of these predicates were also used in contexts where the caller was interested only in success, and would ignore any error messages. In these cases, add a version of the predicate that does not require the extra arguments, and which is semidet (to allow the caller to avoid a test for ok). compiler/error_util.m: Add a mechanism for changing the case of the next format_component, to allow an error message to be appended to a list of format_components providing the context that generates good-looking output whether or not that context is empty. Replace some bools with purpose-specific types. Make sort_error_specs internal to the module, since outside modules should never need to use it. Use cords instead of reversed lists to simplify some parts of the internal implementation. compiler/mercury_to_mercury.m: Provide a mechanism to print out terms only if they aren't too big, for use in our error messages. compiler/prog_item.m: Delete the message_list type, and note a future improvement. compiler/prog_out.m: Delete the predicates for printing message_lists. compiler/intermod.m: compiler/modules.m: Change the way we print out error messages along the lines described at the top. compiler/add_clause.m: compiler/field_access.m: compiler/recompilation.check.m: compiler/recompilation.version.m: compiler/superhomogeneous.m: Conform to the changes above by modifying how we generate error messages. compiler/add_class.m: compiler/add_pragma.m: compiler/check_typeclass.m: compiler/common.m: compiler/make.module_dep_file.m: compiler/make_hlds_error.m: compiler/make_hlds_passes.m: compiler/mercury_compile.m: compiler/mode_errors.m: compiler/modes.m: compiler/options_file.m: compiler/prog_ctgc.m: compiler/prog_event.m: compiler/purity.m: compiler/trans_opt.m: compiler/typecheck.m: Trivial updates to conform to the changes above. compiler/prog_data.m: Add some field names and access functions for use in the modules above. library/list.m: Add list.contains, which is list.member with the arguments reversed to make it possibly to partially apply it. tests/invalid/bad_finalise_decl.err_exp: tests/invalid/bad_initialise_decl.err_exp: tests/invalid/bad_mutable.err_exp: tests/invalid/bigtest.err_exp: tests/invalid/conflicting_fs.err_exp: tests/invalid/constrained_poly_insts.err_exp: tests/invalid/errors.err_exp: tests/invalid/func_errors.err_exp: tests/invalid/fundeps_unbound_in_ctor.err_exp: tests/invalid/fundeps_vars.err_exp: tests/invalid/impl_def_literal_syntax.err_exp: tests/invalid/inst_list_dup.err_exp: tests/invalid/invalid_typeclass.err_exp: tests/invalid/kind.err_exp: tests/invalid/null_char.err_exp: tests/invalid/pragma_source_file.err_exp: tests/invalid/predmode.err_exp: tests/invalid/reserve_tag.err_exp: tests/invalid/some.err_exp: tests/invalid/specified.err_exp: tests/invalid/trace_goal_env.err_exp: tests/invalid/type_vars.err_exp: tests/invalid/typeclass_test_1.err_exp: tests/invalid/typeclass_test_11.err_exp: tests/invalid/typeclass_test_2.err_exp: tests/invalid/unbound_type_vars.err_exp: tests/invalid/unicode1.err_exp: tests/invalid/unicode2.err_exp: tests/invalid/uu_type.err_exp: tests/invalid/vars_in_wrong_places.err_exp: tests/invalid/with_type.err_exp: tests/invalid/purity/purity_nonsense2.err_exp: Update the expected error messages. |
||
|
|
f070e2a1b7 |
Convert the make_hlds stage of the compiler from printing out error messages
Estimated hours taken: 14 Branches: main Convert the make_hlds stage of the compiler from printing out error messages one at a time to gathering them all up and printing them all at once after sorting and deleting duplicates. This approach makes it much easier to be consistent about updating the exit status in the I/O state and the error count in the module info, and indeed this diff fixes some bugs in this area. This approach also means that instead of threading a pair of I/O states through these modules, we now mostly thread through a list of error specifications. In a couple of places, we create the I/O states we need for printing progress messages using trace goals. configure.in: Check that the installed compiler supports trace goals (perhaps with warnings), since the compiler now uses them. compiler/Mercury.options: Temporarily compensate for a bug in the handling of trace goals. compiler/add_class.m: compiler/add_clause.m: compiler/add_mode.m: compiler/add_pragma.m: compiler/add_pred.m: compiler/add_solver.m: compiler/add_type.m: compiler/field_access.m: compiler/foreign.m: compiler/make_hlds_error.m: compiler/make_hlds_passes.m: compiler/make_hlds_warn.m: compiler/module_qual.m: compiler/modules.m: compiler/qual_info.m: compiler/state_var.m: compiler/superhomogeneous.m: Make the change described at the top. In many cases, this required changing code to error util instead of io.write_strings to create the error messages. In some cases, move a predicate used in one module but defined in another module to the first module. Delete some predicates whose job used to be to test options to see whether a message should be generated, since we can now embed the option value that a message depends on in the error message itself. In module_qual.m, remove unnecessary module qualifications. In modules.m, give explicit names to a bunch of lambda expressions. Reformat comments to exploit the available columns. compiler/check_typeclass.m: Conform to the changes above. Mark with XXX the places where we are ignoring the proper update of the error count in module_infos. compiler/modes.m: compiler/post_typecheck.m: compiler/stratify.m: compiler/table_gen.m: compiler/unused_args.m: Use error_specs instead of plain pieces to print error messages. compiler/options.m: Rename an option that conflicts with a language keyword. compiler/handle_options.m: Conform to the change to options.m. compiler/prog_data.m: Rename some function symbols that conflict with language keywords. compiler/prog_out.m: compiler/prog_io_util.m: Conform the change above, and delete some predicates that have now become unused. compiler/mercury_compile.m: Rename a predicate to avoid an ambiguity. Conform to the changes above. compiler/hlds_out.m: compiler/make.module_dep_file.m: compiler/make_hlds.m: compiler/mercury_to_mercury.m: compiler/mode_errors.m: compiler/prog_io.m: Conform to the changes above. In some cases, delete predicates that aren't needed anymore. tests/invalid/errors.err_exp: tests/invalid/errors1.err_exp: tests/invalid/state_vars_test3.err_exp: tests/invalid/undef_inst.err_exp: Update this expected output to reflect the fact that we now sort the error messages. tests/invalid/missing_interface_import2.err_exp: tests/warnings/double_underscore.exp: Update this expected output to reflect the fact that we no longer print the same error message twice. tests/invalid/missing_det_decls.err_exp: Update this expected output to reflect the fact that we now indent an error messages correctly. tests/invalid/multimode_syntax.err_exp: Update this expected output to reflect the fact that we now use error_util instead of plain io.writes to create an error message. tests/invalid/typeclass_test.err_exp: tests/invalid/unsatisfiable_constraint.err_exp: Update this expected output to reflect minor improvements in the formatting of an error message. |
||
|
|
2b2f3d3cbe |
This diff contains no algorithmic changes.
Estimated hours taken: 8 Branches: main This diff contains no algorithmic changes. It merely renames apart a bunch of function symbols to reduce ambiguity. Basically I went through prog_data.m, prog_item.m, hlds_data.m, hlds_goal.m and hlds_pred.m looking for type definitions containing function symbol names that were either language "keywords" (e.g. "terminates", which is an annotation on foreign_procs), used with slightly different meanings in several types (e.g. "sym"), or both (e.g. "call"). When I found such type definitions, I changed the names of the function symbols, usually by adding a prefix or suffix indicating the type to all function symbols of the type. For example, the old function symbol "foreign_proc" in type "pragma_type" is now named "pragma_foreign_proc", and the names of all other function symbols in that type also start with "pragma_". All of this should yield simpler compiler error messages when we make mistakes, and will make it more likely that looking up a function symbol using a tags file will take you to the actual definition of the relevant instance of that function symbol. However, the most important benefit is the increase in the readability of unfamiliar code; the reader won't have to emulate the compiler's type ambiguity resolution algorithm (which in many cases used to require distinguishing between f/14 and f/15 by counting the arguments, e.g. for "pred_or_func"). compiler/prog_data.m: compiler/prog_item.m: compiler/hlds_data.m: compiler/hlds_goal.m: compiler/hlds_pred.m: Rename function symbols as explained above. compiler/*.m: Conform to the function symbol renames. In some cases, rename other function symbols as well. Minor style fixes, e.g. replace if-then-elses with switches, or simple det predicates with functions. |
||
|
|
aeeedd2c13 |
Standardize formatting of comments at the beginning of modules.
compiler/*.m: Standardize formatting of comments at the beginning of modules. |
||
|
|
9d23d8e2e7 |
Implement the trace goal construct we discussed, for now for the LLDS backends
Estimated hours taken: 70
Branches: main
Implement the trace goal construct we discussed, for now for the LLDS backends
only.
Since the syntax of trace goals is non-trivial, useful feedback on syntax
errors inside trace goal attributes is essential. With the previous setup, this
wasn't possible, since the code that turned terms into parse tree goals turned
*all* terms into goals; it couldn't recognize any errors, sweeping them under
the rug as calls. This diff changes that. Now, if this code recognizes a
keyword that indicates a particular construct, it insists on the rest of the
code following the syntax required for that construct, and returns error
messages if it doesn't.
We handle the trace goal attributes that specify state variables to be threaded
through the trace goal (either the I/O state or a mutable variable) in
add_clause.m, at the point at which we transform the list of items to the HLDS.
We handle the compile-time condition on trace goals in the invocation of
simplify at the end of semantics analysis, by eliminating the goal if the
compile-time condition isn't met. We handle run-time conditions on trace goals
partially in the same invocation of simplify: we transform trace goals with
runtime conditions into an if-then-else with the trace goal as the then part
and `true' as the else part, the condition being a foreign_proc that is handled
specially by the code generator, that special handling being to replace
the actual code of the foreign_proc (which is a dummy) with the evaluation of
the runtime condition.
Since these changes require significant changes to some of our key data
structures, I took the liberty of doing some renaming of function symbols
at the same time to avoid using ambiguities with respect to language keywords.
library/ops.m:
Add "trace" as an operator.
compiler/prog_data.m:
Define data types to represent the various attributes of trace goals.
Rename some function symbols to avoid ambiguities.
compiler/prog_item.m:
Extend the parse tree representation of goals with a trace goal.
compiler/mercury_to_mercury.m:
Output the new kind of goal and its components.
compiler/hlds_goal.m:
Extend the HLDS representation of scopes with a scope_reason
representing trace goals.
Add a mechanism (an extra argument in foreign_procs) to allow
the representation of goals that evaluate runtime trace conditions.
Since this requires modifying all code that traverses the HLDS,
do some renames that were long overdue: rename not as negation,
rename call as plain_call, and rename foreign_proc as
call_foreign_proc. These renames all avoid using language keywords
as function symbols.
Change the way we record goals' purities. Instead of optional features
to indicate impure or semipure, which is error-prone, use a plain
field in the goal_info, accessed in the usual way.
Add a way to represent that a goal contains a trace goal, and should
therefore be treated as if it were impure when considering whether to
optimize it away.
Reformat some comments describing function symbols.
compiler/hlds_out.m:
Output the new construct in the HLDS.
compiler/prog_io_util.m:
Generalize the maybe[123] types to allow the representation of more
than one error message. Add functions to extract the error messages.
Add a maybe4 type. Rename the function symbols of these types to
avoid massive ambiguity.
Change the order of some predicates to bring related predicates
next to each other.
compiler/prog_io.m:
compiler/prog_io_dcg.m:
compiler/prog_io_goal.m:
compiler/prog_io_pragma.m:
Rework these modules almost completely to find and accumulate syntax
errors as terms are being parsed. In some cases, this allowed us to
replace "XXX this is a hack" markers with meaningful error-reporting
code.
In prog_io_goal.m, add code for parsing trace goals.
In a bunch of places, update obsolete coding practices, such as using
nested chains of closures instead of simple sequential code, and
using A0 and A to refer to values of different types (terms and goals
respectively). Use more meaningful variable names.
Break up some too-large predicates.
compiler/superhomogeneous.m:
Find and accumulate syntax errors as terms are being parsed.
compiler/add_clause.m:
Add code to transform trace goals from the parse tree to the HLDS.
This is where the IO state and mutable variable attributes of trace
goals are handled.
Eliminate the practice of using the naming scheme Body0 and Body
to refer to values of different types (prog_item.goal and hlds_goal
respectively).
Use error_util for some error messages.
library/private_builtin.m:
Add the predicates referred to by the transformation in add_clause.m.
compiler/goal_util.m:
Rename a predicate to avoid ambiguity.
compiler/typecheck.m:
Do not print error messages about missing clauses if some errors have
been detected previously.
compiler/purity.m:
Instead of just computing purity, compute (and record) also whether
a goal contains a trace goal. However, treat trace goals as pure.
compiler/mode_info.m:
Add trace goals as a reason for locking variables.
Rename some function symbols to avoid ambiguity.
compiler/modes.m:
When analyzing trace goal scopes, lock the scope's nonlocal variables
to prevent them from being further instantiated.
compiler/det_analysis.m:
Insist on the code in trace goal scopes being det or cc_multi.
compiler/det_report.m:
Generate the error message if the code in a trace goal scope isn't det
or cc_multi.
compiler/simplify.m:
At the end of the front end, eliminate trace goal scopes if their
compile-time condition is false. Transform trace goals with runtime
conditions as described at the top.
Treat goals that contain trace goals as if they were impure when
considering whether to optimize them away.
compiler/mercury_compile.m:
Tell simplify when it is being invoked at the end of the front end.
Rename a predicate to avoid ambiguity.
compiler/trace_params.m:
Provide the predicates simplify.m need to be able to evaluate the trace
goal conditions regarding trace levels.
compiler/trace.m:
compiler/trace_gen.m:
Rename the trace module as trace_gen, since "trace" is now an operator.
Rename some predicates exported by the module, now that it is no longer
possible to preface calls with "trace." as a module qualifier.
compiler/notes/compiler_design.html:
Document this name change.
compiler/options.m:
Rename the trace option as trace_level internally, since "trace"
is now an operator. The user-visible name remains the same.
Add the new --trace-flag option.
Delete an obsolete option.
compiler/handle_options.m:
Rename the function symbols of the grade_component type,
since "trace" is now an operator.
compiler/llds.m:
Extend the LLDS with a mechanism to refer to C global variables.
For now, these are used to refer to C globals that will be created
by mkinit to represent the initial values of the environment variables
referred to by trace goals.
compiler/commit_gen.m:
Check that no trace goal with a runtime condition survives to code
generation; they should have been transformed by simplify.m.
compiler/code_gen.m:
Tell commit_gen.m what kind of scope it is generating code for.
compiler/pragma_c_gen.m:
Generate code for runtime conditions when handling the foreign_procs
created by simplify.m.
compiler/code_info.m:
Allow pragma_c_gen.m to record what environment variables it has
generated references to.
compiler/proc_gen.m:
Record the set of environment variables a procedure refers to
in the LLDS procedure header, for efficient access by llds_out.m.
compiler/llds_out.m:
Handle the new LLDS construct, and tell mkinit which environment
variables need C globals created for them.
compiler/pd_util.m:
Rename some predicates to avoid ambiguity.
compiler/*.m:
Conform to the changes above, mainly the renames of function symbols
and predicates, the changed signatures of some predicates, and the new
handling of purity.
util/mkinit.c:
Generate the definitions and the initializations of any C globals
representing the initial status (set or not set) of environment
variables needed by trace goals.
library/assoc_list.m:
Add some predicates that are useful in prog_io*.m.
library/term_io.m:
Minor cleanup.
tests/hard_coded/trace_goal_{1,2}.{m,exp}:
New test cases to test the new construct, identical except for whether
the trace goal is enabled at compile time.
tests/hard_coded/trace_goal_env_{1,2}.{m,exp}:
New test cases to test the new construct, identical except for whether
the trace goal is enabled at run time.
tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
Enable the new test cases.
tests/invalid/*.err_exp:
Update the expected output for the new versions of the error messages
now being generated.
|
||
|
|
459847a064 |
Move the univ, maybe, pair and unit types from std_util into their own
Estimated hours taken: 18 Branches: main Move the univ, maybe, pair and unit types from std_util into their own modules. std_util still contains the general purpose higher-order programming constructs. library/std_util.m: Move univ, maybe, pair and unit (plus any other related types and procedures) into their own modules. library/maybe.m: New module. This contains the maybe and maybe_error types and the associated procedures. library/pair.m: New module. This contains the pair type and associated procedures. library/unit.m: New module. This contains the types unit/0 and unit/1. library/univ.m: New module. This contains the univ type and associated procedures. library/library.m: Add the new modules. library/private_builtin.m: Update the declaration of the type_ctor_info struct for univ. runtime/mercury.h: Update the declaration for the type_ctor_info struct for univ. runtime/mercury_mcpp.h: runtime/mercury_hlc_types.h: Update the definition of MR_Univ. runtime/mercury_init.h: Fix a comment: ML_type_name is now exported from type_desc.m. compiler/mlds_to_il.m: Update the the name of the module that defines univs (which are handled specially by the il code generator.) library/*.m: compiler/*.m: browser/*.m: mdbcomp/*.m: profiler/*.m: deep_profiler/*.m: Conform to the above changes. Import the new modules where they are needed; don't import std_util where it isn't needed. Fix formatting in lots of modules. Delete duplicate module imports. tests/*: Update the test suite to confrom to the above changes. |
||
|
|
25b8b1abc3 |
Fix several performance bugs that showed up when the compiler was invoked on
Estimated hours taken: 20 Branches: main Fix several performance bugs that showed up when the compiler was invoked on Douglas Auclair's training_cars example. Also fix some minor problems that made it harder to find the information needed to localize those problems. training_cars.m is hard to compile quickly because it is big in two dimensions: it has lots of clauses, and each clause has big terms. My laptop still tries to swap itself to death on the full version of training_cars.m (it has only 512 Mb), but the compiler now works fine on a version containing about 20% of its clauses, whereas previously it couldn't compile it at all. In most cases, the changes convert N^2 algorithms to NlogN algorithms. They probably have higher constant factors and may yield small slowdowns for small N, but this is probably not noticeable. Avoiding bad worst case behavior is more important. compiler/superhomogeneous.m: Record the number of goals inserted in each goal being converted to superhomogeneous form. If this exceeds a threshold, wrap a from_ground_term scope around it. Put the predicates into a more cohesive sequence. compiler/field_access.m: Work with the code in superhomogeneous to record the number of inserted goals. Reorder the arguments of some performances to be consistent with the predicates in superhomogeneous.m. compiler/modes.m: Use the from_ground_term scope to reverse the list of inserted unifications if necessary. It is much more efficient to do this here than to let it happen by sequences of delays and wakeups. That would have quadratic complexity; this is linear. This is what I originally introduced from_ground_term scopes for. Then, the overhead was too high, because I added one scope per function symbol. This version should be fine, since there is at most one scope added per argument of an atom (clause head or call). compiler/modes.m: compiler/unique_modes.m: When we are processing goals inside a from_ground_term scope, record this fact. compiler/mode_info.m: Make it possible to record this fact. compiler/modecheck_unify.m: When we are inside a from_ground_term scope, don't try to update the insts of vars on the right hand sides of construction unifications. Since these variables came from expansion to superhomogeneous form, those variables won't occur in any following code, so updating their state is useless, and the algorithm we used to do so is linear in the size of the inst. Since the size of an inst of a variable that results from superhomogeneous expansion is itself on average proportional to the size of the original term, this change turns a quadratic algorithm into a linear one. compiler/inst_match.m: Use balanced trees instead of ordered lists to represents sets of expansions, since these sets can be large. Note an opportunity for further improvement. compiler/inst_util.m: Note another opportunity for further improvement. compiler/instmap.m: Rename several predicates to avoid ambiguities. compiler/cse_detection.m: We used to print statistics for the processing of each procedure without saying which procedure it is for; fix this. compiler/switch_detection.m: Don't print progress messages for predicates with no procedures, since they would be misleading. compiler/higher_order.m: Change an algorithm that was quadratic in the number of arms for merging the information from the different arms of disjunctions and switches to an NlogN algorithm. Change the algorithm for merging the info from two branches that quadratic in the number of variables per arm to an NlogN algorithm. Changed some type equivalences to notag types to aid robustness. compiler/quantification.m: Rename several predicates to avoid ambiguities. The sets of variables in different arms of disjunctions and switches tend to have relatively small intersections. Yet the algorithms we used to compute the set of variables free in the disjunction or switch included the variables from the already processed arms in the sets being accumulated when processing later arms, leading to the quadratic behavior. This diff changes the algorithm to process each arm independently, and then use a more balanced algorithm to summarize the result. Specialize the predicates that compute sets of free vars in various HLDS fragments to work either with ordinary_nonlocals or code_gen_nonlocals without making the same decision repeatedly. Move some code out of large predicates into predicates of their own. compiler/Mercury.options: Specify the compiler option that can exploit this specialization to make the code run faster. compiler/simplify.m: Use a more efficient data structure for recording the parameters of an invocation of simplification. Change some predicate names and function symbol names to avoid ambiguity. compiler/common.m: compiler/deforest.m: compiler/deforest.m: compiler/make_hlds_warn.m: compiler/mercury_compile.m: compiler/pd_util.m: compiler/stack_opt.m: compiler/term_constr_build.m: Conform to the changes in simplify.m and/or instmap.m. compiler/mercury_compile.m: Fix a bug in progress messages for polymorphism.m. compiler/equiv_type_hlds.m: Most of the time, substitutions inside insts have no effect, because very few insts include any reference to a types. Instead of the old approach of building new insts and then throwing them away if they are the same as the old ones, don't build new insts at all if the old inst contains no types. compiler/common.m: Change some predicate names to make them clearer. compiler/hlds_clauses.m: Record the number of clauses so far, to allow a more informative progress message to be printed. compiler/add_clause.m: Print this more informative progress message. Conform to the changes in superhomogeneous.m. compiler/code_gen.m: Use the context of the predicate's first clause (which will be the context of the first clause head) as the context of the predicate's interface events. Unlike the context of the body goal, this won't be affected by program transformations such as wrapping a from_ground_term scope around some goals. It is better for users anyway, since the old policy lead to contexts in the middle of procedure bodies if the top level goal was a disjunction, switch or if-then-else. tests/debugger/*.exp: Update the expected outputs to conform to the change to code_gen.m. |
||
|
|
be5b71861b |
Convert almost all the compiler modules to use . instead of __ as
Estimated hours taken: 6 Branches: main compiler/*.m: Convert almost all the compiler modules to use . instead of __ as the module qualifier. In some cases, change the names of predicates and types to make them meaningful without the module qualifier. In particular, most of the types that used to be referred to with an "mlds__" prefix have been changed to have a "mlds_" prefix instead of changing the prefix to "mlds.". There are no algorithmic changes. |
||
|
|
c751cf87fc |
Remove now incorrect errors of the form "unification with expression was
Estimated hours taken: 2 Branches: main Remove now incorrect errors of the form "unification with expression was declared impure, but expression was not a function call." compiler/purity.m: Prevent purity.m from reporting unifications marked with impure as errors: unifications *can* be impure if they unify two inst any variables in a negated context. Purity error reporting for unifications is now handled in modecheck_unify.m. compiler/field_access.m: compiler/superhomogeneous.m: Include unification impurity annotations in the corresponding goal infos, rather than discarding them or reporting an error. tests/invalid/purity/impure_func_t7.err_exp: tests/invalid/purity/impure_func_t7.m: Break the test cases into separate predicates. Update the expected error output. doc/reference_manual.texi: Make the section on purity annotations clearer and up-to-date. |
||
|
|
5f589e98fb |
Various cleanups for the modules in the compiler directory.
Estimated hours taken: 4 Branches: main Various cleanups for the modules in the compiler directory. The are no changes to algorithms except the replacement of some if-then-elses that would naturally be switches with switches and the replacement of most of the calls to error/1. compiler/*.m: Convert calls to error/1 to calls to unexpected/2 or sorry/2 as appropriate throughout most or the compiler. Fix inaccurate assertion failure messages, e.g. identifying the assertion failure as taking place in the wrong module. Add :- end_module declarations. Fix formatting problems and bring the positioning of comments into line with our current coding standards. Fix some overlong lines. Convert some more modules to 4-space indentation. Fix some spots where previous conversions to 4-space indentation have stuffed the formatting of the code up. Fix a bunch of typos in comments. Use state variables in more places; use library predicates from the sv* modules where appropriate. Delete unnecessary and duplicate module imports. Misc. other small cleanups. |
||
|
|
f9fe8dcf61 |
Improve the error messages generated for determinism errors involving committed
Estimated hours taken: 8
Branches: main
Improve the error messages generated for determinism errors involving committed
choice contexts. Previously, we printed a message to the effect that e.g.
a cc pred is called in context that requires all solutions, but we didn't say
*why* the context requires all solutions. We now keep track of all the goals
to the right that could fail, since it is these goals that may reject the first
solution of a committed choice goal.
The motivation for this diff was the fact that I found that locating the
failing goal can be very difficult if the conjunction to the right is
a couple of hundred lines long. This would have been a nontrivial problem,
since (a) unifications involving values of user-defined types are committed
choice goals, and (b) we can expect uses of user-defined types to increase.
compiler/det_analysis.m:
Keep track of goals to the right of the current goal that could fail,
and include them in the error representation if required.
compiler/det_report.m:
Include the list of failing goals to the right in the representations
of determinism errors involving committed committed choice goals.
Convert the last part of this module that wasn't using error_util
to use error_util. Make most parts of this module just construct
error message specifications; print those specifications (using
error_util) in only a few places.
compiler/hlds_out.m:
Add a function for use by the new code in det_report.m.
compiler/error_util.m:
Add a function for use by the new code in det_report.m.
compiler/error_util.m:
compiler/compiler_util.m:
Error_util is still changing reasonably often, and yet it is
included in lots of modules, most of which need only a few simple
non-parse-tree-related predicates from it (e.g. unexpected).
Move those predicates to a new module, compiler_util.m. This also
eliminates some undesirable dependencies from libs to parse_tree.
compiler/libs.m:
Include compiler_util.m.
compiler/notes/compiler_design.html:
Document compiler_util.m, and fix the documentation of some other
modules.
compiler/*.m:
Import compiler_util instead of or in addition to error_util.
To make this easier, consistently use . instead of __ for module
qualifying module names.
tests/invalid/det_errors_cc.{m,err_exp}:
Add this new test case to test the error messages for cc contexts.
tests/invalid/det_errors_deet.{m,err_exp}:
Add this new test case to test the error messages for unifications
inside function symbols.
tests/invalid/Mmakefile:
Add the new test cases.
tests/invalid/det_errors.err_exp:
tests/invalid/magicbox.err_exp:
Change the expected output to conform to the change in det_report.m,
which is now more consistent.
|
||
|
|
b2012c0c0e |
Rename the types 'type', 'inst' and 'mode' to 'mer_type', 'mer_inst'
Estimated hours taken: 8 Branches: main compiler/*.m: Rename the types 'type', 'inst' and 'mode' to 'mer_type', 'mer_inst' and 'mer_mode'. This is to avoid the need to parenthesize these type names in some contexts, and to prepare for the possibility of a parser that considers those words to be reserved words. Rename some other uses of those names (e.g. as item types in recompilation.m). Delete some redundant synonyms (prog_type, mercury_type) for mer_type. Change some type names (e.g. mlds__type) and predicate names (e.g. deforest__goal) to make them unique even without module qualification. Rename the function symbols (e.g. pure, &) that need to be renamed to avoid the need to parenthesize them. Make their replacement names more expressive. Convert some more modules to four space indentation. Avoid excessively long lines, such as those resulting from the automatic substitution of 'mer_type' for 'type'. |
||
|
|
5662974ccc |
Add forgotten file.
Estimated hours taken: 0.1 Branches: main compiler/field_access.m: Add forgotten file. |