Commit Graph

262 Commits

Author SHA1 Message Date
Zoltan Somogyi
012751691c Rename some function symbols to avoid ambiguity.
compiler/module_qual.id_set.m:
    As above. Also give the affected type a better name.

compiler/module_qual.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
    Conform to the change above.
2022-11-25 16:23:33 +11:00
Zoltan Somogyi
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.
2022-10-12 20:50:16 +11:00
Zoltan Somogyi
07f877bc3f Carve term_context.m out of term.m.
library/term.m:
library/term_context.m:
    As above.

    Rename the term.context type as term_context.term_context, with
    term.context now being defined as an equivalence type.

    Replace the context_init function and predicate and the dummy_context_init
    function with just one function: dummy_context. This name includes
    the important part (the fact that it return a *dummy* context) and deletes
    the nonimportant part (dummy contexts are just about never updated,
    so the function does not really "initialize" them).

    Reduce function/predicate pairs that do the same thing to just a function.

library/MODULES_DOC:
library/library.m:
    Add the new module to the list of standard library modules.

NEWS:
    Mention the new module, and the obsoleting of the moved predicates
    and functions in term.m.

compiler/*.m:
library/*.m:
    Conform to the changes above.
2022-08-23 12:56:37 +10:00
Zoltan Somogyi
428aa400eb Introduce aug_make_int_unit.
compiler/prog_item.m:
    Split aug_compilation_unit into two types. One, aug_make_int_unit,
    is a new type, and it is a version of the old aug_compilation_unit
    that contains only what is needed when making .int{,0,2} files.
    The other, the new aug_compilation_unit, contains what is needed
    when generating target language code. Both encode in their argument types
    stronger invariants that the old aug_compilation_unit type did.

compiler/comp_unit_interface.m:
compiler/decide_type_repn.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.m:
compiler/parse_tree_out.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
    Conform to the change above.

    In some cases, this means passing around aug_make_int_units instead of
    aug_compilation_units.

    In a few cases, it means creating two copies of a predicate,
    one for aug_compilation_units and one for aug_make_int_units.
    In such cases, factor out any commonalities between the copies.

    In many cases, it means updates to account for the specialized types
    of the fields of aug_compilation_unit or aug_make_int_unit.

    In some cases, it means deleting code that was always unreachable,
    but the not-tight-enough types did not make this fact visible.
    (Due to this effect, this diff removes more lines than it adds.)
2021-08-17 19:23:55 +10:00
Zoltan Somogyi
5c3d4fe4f0 Replace module_and_imports with aug_compilation_unit.
compiler/module_imports.m:
    Delete the module_and_imports type, and replace its uses with
    aug_compilation_units.

    The structure of module_and_imports used to be private, but the
    structure of aug_compilation_units is public. Delete the getter/setter
    predicates on module_and_imports structures that can now be done
    using field names on aug_compilation_units. Delete, along with this,
    the infrastructure for keeping track of which module_and_imports fields
    are ever accessed. It has served its purpose, but it won't be needed
    anymore.

    Change types that used to include module_and_imports to include
    aug_compilation_units instead.

    Rename any types, predicates and functions that used to contain
    the "module_and_imports" string in their name.

compiler/prog_item.m:
    Move the version number map to be the last field of aug_compilation_units,
    as it used to be in module_and_imports structures, since this fits better.

compiler/get_dependencies.m:
    Make the name of a predicate more reflective of the type it returns.

compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/generate_dep_d_files.m:
compiler/grab_modules.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make_hlds_separate_items.m:
compiler/mercury_compile_main.m:
compiler/module_qual.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.
2021-08-17 09:11:53 +10:00
Zoltan Somogyi
d84571c0c2 Delete redundant fields in aug_compilation_units.
compiler/prog_item.m:
    Delete the module name and module name context fields from
    aug_compilation_units, since the same info is available from
    the parse_tree_module_src field.

compiler/comp_unit_interface.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/mercury_compile_main.m:
compiler/module_imports.m:
compiler/module_qual.m:
compiler/prog_item_stats.m:
compiler/write_deps_file.m:
    Conform to the change above.
2021-07-20 06:13:55 +10:00
Zoltan Somogyi
e627efcf50 A start on getting type_repn info from .int files.
compiler/du_type_layout.m:
    Add a first draft of the code that will eventually get type representation
    information from .int files. Invoke the new code only if undocumented,
    developer-only experiment flags are set, and when invoked, compare
    its output with the output of the old algorithm it is intended to
    eventually replace.

    The new code is not yet complete, and thus has not yet been tested.

compiler/prog_item.m:
    Add a new field to the augmented compilation unit data type
    that is intended to hold the .int file of the main module, the module
    that the augmented compilation unit is for. For every module imported
    by the main module, we read its .int or .int2 file and get the
    representation information for the types they define from those files,
    but we need this info for the main module's own types as well.

    Add "need type representation information" as reason for reading
    a .int file.

    Break some types down into smaller types, to allow their components
    to be manipulated individually by du_type_layout.m.

    Start using uint8, not uint, in situations where we want to store
    values that select bits in words, which fit into 6 bits.

    Add XXXs where we could, and maybe should switch to uint8s.

    Add extra documentation.

compiler/grab_modules.m:
    Read in the main module's own .int file.

    Replace a bool with a bespoke type.

compiler/module_imports.m:
    Provide a slot for the main module's own interface file,
    which will be used to set the new slot in augmented compilation units.

compiler/comp_unit_interface.m:
    Put the exact same type_ctor_repn_map into .int2 files as .int files.
    This should prevent the scenario where a compilation reads
    e.g. mod_x.int2, gains access to the definitions of the exported types
    of module mod_x,  but then needs to read mod_x.int as well to find out
    how those types are represented. Since neither type checking nor any
    other semantic analysis pass pays any attention to type_repn items,
    the additional type_repn items in mod_x.int2 cannot turn an otherwise
    illegal program into a legal one.

compiler/hlds_data.m:
    Clarify a comment.

compiler/maybe_error.m:
    Provide a utility predicate.

compiler/prog_data.m:
    Add XXXs about possible future improvements.

compiler/decide_type_repn.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_type_repn.m:
compiler/parse_type_repn.m:
compiler/prog_item_stats.m:
compiler/write_deps_file.m:
    Conform to the changes above.
2021-07-01 06:12:21 +10:00
Zoltan Somogyi
93c306916a Specify streams explicitly in more modules.
compiler/module_cmds.m:
    Require all callers to specify output streams explicitly.

compiler/compile_target_code.m:
    Require callers to specify output streams explicitly in most cases.

    In the remaining cases, add "XXX STREAM" comments to request that
    the explicit streams be passed later.

    Add XXXs where preserving old behavior results in wrong-looking code.

    Modify the signature of compile_java_files to encode the invariant that
    the list of Java files given to it may not be empty.

compiler/error_util.m:
    Provide a version of an error predicate that takes explicit streams.

compiler/make.build.m:
    Mark predicates that help redirect implicit streams as predicates
    that should not be used.

compiler/make.module_target.m:
compiler/make.program_target.m:
    Add "XXX STREAM" comments to request that the explicit streams
    be passed later.

compiler/module_qual.m:
    Provide a means to construct the debug output stream.

compiler/module_qual.collect_mq_info.m:
    Use the debug output stream where relevant.

compiler/analysis.m:
compiler/export.m:
compiler/recompilation.check.m:
compiler/source_file_map.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
    Conform to the changes above, mostly by passing explicit streams.

compiler/Mercury.options:
    Stop specifying --no-warn-implicit-stream-calls for the above modules
    (those that had it specified in the first place).

    Delete a long-unneeded workaround.

compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
    Specify progress and output streams explicitly when calling the modules
    above (not in other places, just yet).
2021-05-17 22:55:06 +10:00
Zoltan Somogyi
edbbce3193 Avoid a pass over aug_compilation_units.
compiler/module_qual.m:
    The mqsi_imported_modules field is used only for one purpose:
    to decide whether to add "No module named xyz has been imported"
    to error messages. Document this fact.

    Don't compute the set of implicitly imported modules to put
    into this field. We do these implicit imports to allow the *compiler*
    to generate *fully qualified* references to entities defined in these
    modules; they are *not* there to be used directly by programmers.
    If programmers want to use them, they should import them, so a message
    along the lines above is warranted if they get this wrong.
2020-05-26 08:32:38 +10:00
Zoltan Somogyi
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.
2020-03-13 12:58:33 +11:00
Zoltan Somogyi
36c2000516 Add the one_or_more and one_or_more_map modules to the library.
library/one_or_more.m:
    We used to have a type named one_or_more in the list module representing
    nonempty lists. It had literally just two predicates and two functions
    defined on it, three of which did conversions to and from lists, which
    limited their usefulness.

    This new module is the new home of the one_or_more type, together with
    a vastly expanded set of utility predicates and functions. Specifically,
    it implements every operation in list.m which makes sense for nonempty
    lists.

library/list.m:
    Delete the code moved over to one_or_more.m.

library/one_or_more_map.m:
    This new module is a near copy of multi_map.m, with the difference being
    that while the multi_map type defined in multi_map.m maps each key
    to a list(V) of values (a list that happens to always be nonempty),
    the one_or_more_map type defined in one_or_more_map.m maps each key
    to a one_or_more(V) of values (which enforces the presence of at least
    one value for each key in the type).

library/map.m:
    Mention the existence of one_or_more_map.m as well as multi_map.m.

library/MODULES_DOC:
library/library.m:
    List the new modules as belonging to the standard library.

NEWS:
    Mention the new modules, and the non-backwards-compatible changes to
    list.m.

compiler/*.m:
    Import the one_or_more module when needed.

tests/hard_coded/test_one_or_more_chunk.{m,exp}:
    Test the one predicate in one_or_more.m that is non-trivially different
    from the corresponding predicate in list.m: the chunk predicate.

tests/hard_coded/Mmakefile:
    Enable the new test case.
2020-02-28 14:29:05 +11:00
Zoltan Somogyi
4ef4402ecf Make --warn-inconsistent-pred-order-clauses default for the compiler.
compiler/COMP_FLAGS.in:
    As above.

compiler/Mercury.options:
    List the modules for we need --no-warn-inconsistent-pred-order-clauses
    for now.

compiler/call_gen.m:
compiler/code_util.m:
compiler/deep_profiling.m:
compiler/equiv_type.m:
compiler/error_util.m:
compiler/exprn_aux.m:
compiler/get_dependencies.m:
compiler/global_data.m:
compiler/layout_out.m:
compiler/liveness.m:
compiler/ll_pseudo_type_info.m:
compiler/llds.m:
compiler/llds_out_code_addr.m:
compiler/llds_out_data.m:
compiler/module_cmds.m:
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
compiler/opt_debug.m:
compiler/parse_class.m:
compiler/parse_goal.m:
compiler/parse_sym_name.m:
compiler/parse_type_defn.m:
compiler/rtti_out.m:
compiler/stack_layout.m:
compiler/trace_gen.m:
    Fix issues reported by --warn-inconsistent-pred-order-clauses
    for these modules.
2019-08-23 18:36:18 +10:00
Zoltan Somogyi
615d2795c8 Take foreign_import_modules out of the item type.
compiler/prog_item.m:
    Even though we express foreign import module declarations syntactically
    as pragmas, semantically, they are much closer to import_module
    declarations. This means that the treatment they require in most places
    in the compiler is similar to the treatment of import_module declarations,
    and quite different from the treatment of other kinds of items.
    Therefore this diff takes foreign_import_module declarations (FIMs
    for short) out of item type. From now on, in parse trees and their
    components, FIMs are stored in data structures of their own, next to
    import_module declarations.

compiler/parse_types.m:
    Provide a mechanism for the parser to return FIMs as an entity kind
    of its own, not as an item.

compiler/comp_unit_interface.m:
    Conform to the changes above, and give a predicate a more specific name.

compiler/module_qual.m:
    Conform to the changes above, and require .int3 files to contain no FIMs.

compiler/canonicalize_interface.m:
compiler/check_raw_comp_unit.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/hlds_module.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/module_imports.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qualify_items.m:
compiler/parse_module.m:
compiler/parse_pragma.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/split_parse_tree_src.m:
    Conform to the changes above.
2019-08-22 09:31:10 +10:00
Zoltan Somogyi
b6a5a97335 Module qualify .int3 files just once.
compiler/module_qual.m:
    Rename module_qualify_parse_tree_int as module_qualify_parse_tree_int3,
    since it is used only to module qualify .int3 files.

    Resolve an old XXX inside it about the treatment of implementation sections
    by requiring the implementation section to be empty (which it always is
    in .int3 files).

compiler/comp_unit_interface.m:
    Conform to the change above.

compiler/write_module_interface_files.m:
    Don't call module_qualify_parse_tree_int3, since the predicate in
    comp_unit_interface we just called has already done that.
2019-06-30 12:16:50 +02:00
Zoltan Somogyi
466bcfbc5c Add direct code for creating module_and_imports structures.
compiler/modules.m:
    The two main top-level predicates in this module grab the
    qualified and unqualified interface files respectively of the modules
    that the given raw compilation unit depends on.

    Before the grabbing part can begin, they both need to create
    the initial version of the module_and_imports structure.
    The code they use to do this is hard to understand for several reasons:

    - they do this in many separate passes over the compilation unit's
      item blocks;
    - some of those passes are over *modified* versions of the item blocks;
    - many of the passes are in other modules.

    This diff adds new code to do the same job more directly:

    - the new code has many fewer passes;
    - none of those passes are over modified data structures;
    - all the code is in modules.m.

    For a transition period, execute both the old and new code,
    and require their output to be the same (modulo irrelevant details)
    as a sanity check.

    At the end of that period, we should be able to delete the sanity check,
    the code of the old algorithm in modules.m, and the predicates in other
    modules whose only caller was the old algorithm.

compiler/comp_unit_interface.m:
    Export a predicate for use by the new code in modules.m.

    Add a note about soon-to-be-obsolete code.

compiler/get_dependencies.m:
    Export several related predicates, and the types they need,
    for use by the new code in modules.m.

    Simplify those predicates by not making them record a context
    for the module names they collect. The context being recorded
    was always a dummy, which is not useful.

    Add a note about soon-to-be-obsolete code.

compiler/hlds_module.m:
compiler/module_qual.m:
    Conform to the change in get_dependencies.m.

compiler/module_imports.m:
    Conform to the change in get_dependencies.m.

    Note possibilities for future improvement.
2019-04-20 05:05:51 +10:00
Zoltan Somogyi
b70bdb2d95 Delete the context field from item_blocks.
compiler/prog_item.m:
    The context field in item_blocks was used only in setting the context
    fields of other item blocks. There was no end user, and many places
    that created item_blocks ab initio put a dummy value into the field
    anyway, so this diff deletes the field.

    The intent is to prepare for future changes to the module_and_imports
    structure that replace lists of item blocks, each which may be
    of any section, with just one list of items, one list of includes
    and one list of avails per section kind.

    In some places, this should allow us to avoid searching item blocks
    for the right sections; in other places, it should allow us to replace
    two nested loops (on blocks and on e.g. items) with just one loop
    (e.g. on items).

    We do still record section contexts during parsing, because this is
    needed for the context of some error messages (e.g. the one we generate
    for an implementation section in a submodule that is included in the
    interface section of its parent module).

compiler/check_raw_comp_unit.m:
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/make.module_dep_file.m:
compiler/make_hlds_separate_items.m:
compiler/module_imports.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
compiler/modules.m:
compiler/parse_module.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
compiler/recompilation.check.m:
compiler/split_parse_tree_src.m:
    Conform to the change above.
2019-04-16 06:16:52 +10:00
Zoltan Somogyi
df47de186b Tighten module accessibility rules.
NEWS:
    Announce this fact.

compiler/modules.m:
    If module m.n imports module x.y.z, require it to import its ancestor
    modules (x and x.y).

    If module m.n imports module x.y.z in the interface, require it to import
    its ancestor modules (x and x.y) in the interface.

    If module m.n imports module x.y.z, require us to see an include for z in
    x.y, if we see an interface file for x.y.

    Given a module m.n, require us to see an include for n in m's private
    interface file.

    These rules are tighter than the rules we enforced before.

    Report any violations of the above rules when generating code for m.n.
    Previously, we also reported violations when generating interface files.

compiler/prog_item.m:
    For each item block, record which module it came from. (We have long
    recorded which *section* of that module it came from.) This is needed
    by some of the new functionality in modules.m.

    Likewise, record the module name in the module components (from which
    item blocks are later constructed).

compiler/parse_module.m:
    Record the module name in module components and item blocks.

compiler/check_raw_comp_unit.m:
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/make.module_dep_file.m:
compiler/make_hlds_separate_items.m:
compiler/module_imports.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
compiler/recompilation.check.m:
compiler/split_parse_tree_src.m:
    Conform to the changes above.

tests/invalid/missing_parent_import.err_exp:
    Expect an additional error message we now generate.

tests/invalid/sub_c.err_exp:
tests/invalid/test_nested.err_exp:
    Expect the more specific error messages we now generate.
2019-03-31 09:22:26 +11:00
Zoltan Somogyi
4bcb3fd227 Add XXXs for possible unnecessary duplication of work. 2019-02-02 23:50:00 +11:00
Zoltan Somogyi
fb97df69ed Make "compute type representations" a separate pass.
The ultimate purpose of this diff is to prepare for future improvements
in type representations, allowing values of some data types to be represented
more compactly than up to now.

The main way this diff does that is by creating a separate pass for deciding
how values of each type should be represented. We have traditionally decided
data representations for each type as its type definition was processed
during the make_hlds pass, but these decisions were always tentative,
and could be overridden later, e.g. when we processed foreign_type or
foreign_enum pragmas for the type. This dispersed decision making algorithm
is hard to understand, and therefore to change.

This diff centralizes decisions about type representations in a separate
pass that does nothing else. It leaves the algorithm distributed among
several files (du_type_layout.m, make_tags.m, and add_foreign_enum.m) for now,
to make reviewing this diff easier, but soon after it is committed I intend
to move all the relevant code to du_type_layout.m, to centralize the decision
code in "space" as well as in time.

For the reason why this pass runs before any of the semantic analysis
passes, instead of after all of them as I originally intended and as we
discussed on m-dev in late october 2017, see the big comment at the start of
du_type_layout.m.

As per another part of that same discussion on m-dev, this diff
makes a start on implementing a new type of item, the type_repn item,
which is intended *only* to be used in compiler-generated interface files,
*not* in source files. It is only a start because we can use these items
only *after* the creation of a separate type representation decision pass,
and this diff is already very big. The code for making the compiler understand
these items will be added later. The code for generating them will be added
later still, once the code for understanding them has been installed on
all our systems.

Since I was going to be working on the affected code anyway, this diff
also carries out two other decisions that came out of that discussion:

- the deletion of the ability to reserve a tag in a type for HAL,
  either via a compiler option or via a pragma, and

- the deletion of the ability to represent a functor using the address
  of a statically allocated object (which we haven't used and won't use,
  because it slows down accesses to *all the other functors* of the type).

compiler/mercury_compile_front_end.m:
    Invoke the new pass for making decisions about type representations
    after the make_hlds pass. (We used to do only the final part of it then.)

    Fix a bad dump stage name.

    Add an extra check for what it means for a module to be error free.

    Make a sub-switch explicit.

compiler/hlds.m:
compiler/make_hlds.m:
    Move the modules that implement the new pass from the make_hlds package
    to the hlds package, to give the compiler's top level access to them.

    Make the same move for the modules that the new pass's modules need.
    Since they are now part of hlds, they cannot reach into make_hlds,
    and I think this is a cleaner solution than forwarding predicates.

    Delete some forwarding predicates that are no longer needed.

compiler/notes/compiler_design.html:
    Document the updated location of the moved modules.

    Add an XXX to note a place where the documentation has not been
    updated in the past.

compiler/du_type_layout.m:
    Add code to implement the new pass.

    Keep the algorithm for deciding type representations as close
    to the previously used algorithm as possible, since this diff
    is already big enough. (The previous algorithm was scattered across
    add_type.m, add_foreign_enum.m, and make_hlds_passes.m.)

    Simplifications and optimizations will come later, after this module
    is merged with make_tags.m and with (at least) the foreign_enum half of
    add_foreign_enum.m.

compiler/make_tags.m:
    Keep the functionality of this module, which does both the first part
    of deciding type representations (tentatively assigning tags to functors,
    an assignment that may be overridden later), and the last part (packing
    multiple adjacent less-than-word-sized enum args into a single word,
    if possible.), but simplify it where possible, and note possibilities
    for further improvements.

compiler/add_foreign_enum.m:
    This module has two halves, one dealing with foreign_enum pragmas
    and one dealing with foreign_export_enum pragmas.

    Change the half that deals with foreign_enum pragmas to just build
    a data structure that du_type_layout.m will need to make its decisions,
    this structure being a map from type_ctors to the foreign enum
    specification applicable to the current target language. Include
    in this structure a component that add_foreign_enum.m itself can use
    to report better error messages for duplicate foreign_enum pragmas;
    this component records, for each type_ctor and language, the context
    of the previous foreign_enum pragma for that combo.

    Change the input for the half that deals with foreign_export_enum pragmas
    to reflect the fact that it is invoked by du_type_layout.m after all
    decisions about type representations have already been made.

compiler/add_special_pred.m:
    Move this module from the make_hlds package to the hlds package,
    since the code that adds special preds for type is now called from
    du_type_layout.m.

    Change the names of predicates to make clear whether they add
    only the declaration of a predicate, only its definition, or both.

    Don't try to pre-guess whether the implementation of a type's
    compare predicate will need an index predicate. Let the code
    that generates calls to the index predicate both declare and define
    the index predicate. This change removes the potential for
    inconsistencies between the two pieces of code.

compiler/add_pred.m:
    Move this module from the make_hlds package to the hlds package,
    since add_special_pred.m needs access to it.

compiler/add_type.m:
    When adding a type definition to the HLDS, don't try to decide
    its representation. Any such decision was tentative anyway, due
    to the possibility of e.g. the later processing of foreign_type
    or foreign_enum pragmas for the type. Likewise, don't try to
    create the special (unify, compare) predicates for the type.
    Leave both tasks to the du_type_layout pass.

    Likewise, don't try to pack the representation of types, or record
    no_tag types in the table of no_tag types, during the post-processing
    pass either; leave both of these to du_type_layout as well.
    Rename the predicate that post_processes type definitions to reflect
    the two tasks left for it to do.

compiler/prog_data.m:
    Do not store width information about the arguments of those data
    constructors in the parse tree. That information is not computed
    until later; until then, it was always filled in with dummy values.
    (But see hlds_data.m below.)

    Use bespoke types to represent the presence or absence of user-specified
    unify and compare predicates.

    Change the representation of data constructors to use a single "maybe"
    type, not two lists, to denote the presence or absence of existentially
    typed arguments.

    Give the HLDS the ability to hold representation information about
    abstract types that in the future we will get from type_repn items
    in the defining modules' interface files.

    Delete the uses_reserved_tag type, since we never use reserved tags
    anymore.

compiler/prog_item.m:
    Add the new type_repn item type, which is not used yet.

    Delete the reserve_tag pragma.

    Fix an earlier mistake in the wording of a context message.

compiler/hlds_data.m:
    Put all the fields of hlds_du_type (the type definition variant dealing
    with discriminated union types) that deal with type representation
    issues in a single "maybe" field that is set to "no" before the
    type representation decision pass has been run.

    Add new type, constructor_repn, that stores the same information as the old
    constructor type (defined in prog_data.m), PLUS the information
    describing how terms with that data constructor are stored.

    Likewise, add a new type ctor_arg_rep, which likewise stores
    the widths of each constructor argument. When we implement
    argument reordering, we would store the offset of the arg as well.

    Since the parse tree representations of constructors and their arguments
    don't store representation information anymore, the cons_table they
    are stored in doesn't either. Make the lookup of representation information
    for a given constructor possible by adding a map to the new "maybe" field
    of hlds_du_type.

    Provide some utility predicates.

    Optimize some existing predicates.

    Rename some types to better reflect their meaning.

compiler/hlds_module.m:
    Provide a slot in the module_info for storing the information
    gathered by make_hlds.m that is needed by the new pass.

compiler/make_hlds_separate_items.m:
    When we see either a foreign_enum or a foreign_export_enum pragma,
    return values of a bespoke type for them (a type defined in
    hlds_module.m), instead of an item_pragma. This makes handling them
    considerably easier.

compiler/make_hlds_passes.m:
    With the changes in this diff, adding a type to the HLDS won't
    decide its representation. Therefore delete the code that used
    to loop over foreign_export_enum pragmas; in the absence of
    the final type representation information, it won't work right.

    Record the information that the du_type_layout pass will need
    in the module_info.

compiler/add_pragma.m:
    Delete the code for passing on foreign_enum and foreign_export_enum
    pragmas to add_foreign_enum.m; they are now passed to add_foreign_enum.m
    by du_type_layout.m.

    Move a utility predicate to make_hlds_error.m, to allow add_foreign_enum.m
    to call it.

compiler/make_hlds_error.m:
    Add the utility predicate moved from add_pragma.m.

    Move the module from the make_hlds to the hlds package.

compiler/module_qual.m:
    Provide a mechanism for recording error messages about e.g. undefined
    types without recording that we found an undefined type. This sounds
    strange, but there is a valid use case.

    When a type definition declares a functor's argument to be of an
    undefined type, that error is usually fatal; we stop the compiler
    from proceeding even to typechecking, since the typechecker will
    probably abort with a map lookup failure. Most other references
    to undefined types are similarly fatal for the same reason. However,
    if e.g. a foreign_export_enum pragma refers to an undefined type,
    that error *won't* be visible to the typechecker, and therefore
    won't crash it. The error will still cause the compiler to exit
    without generating any target language code, but at least it will be
    able to run the typechecker and other semantic analysis passes.

    Without this change, the compiler will report only one error in
    the ee_invalid.m test case; with it, it reports *every* error
    in the test case expected output.

compiler/module_qual.qualify_items.m:
    Use the capability describe above for undefined types in
    foreign_export_enum pragmas.

compiler/module_qual.qual_errors.m:
    Delete a (somewhat incorrect) copy of a predicate in prog_item.m,
    to reduce code duplication.

compiler/prog_type.m:
    Add ways to represent abstract types whose representations are nevertheless
    known (from type_repn items in the defining modules' interface files)
    to be notag or dummy types. This will be needed to fix Mantis bug #441,
    a fix that will probably be one of the first later changes to build
    on this diff.

    Delete a type moved to type_util.m.

compiler/type_util.m:
    Provide extra versions of some predicates, with the difference between
    the old and the new versions being that one requires type representations
    to have been decided already, and the other one does not.

    Move the definition of the ctor_defn type here from prog_type.m,
    since prog_type.m itself does not use it, but type_util.m does.

    Give some predicates more meaningful names.

compiler/parse_type_defn.m:
    Simplify the code for parsing type definitions, to make it easier
    to reuse to parse type_repn items.

    Add a sanity check that requires existential constraints to have
    *some* existential variables to apply to.

    Allow "type_is_representable_in_n_bits" as a synonym for
    "type_is_abstract_enum", since in the future we want to be able to pack
    e.g. multiple int8s, not just multiple enums, into a single word.

    Generate more specific error messages for some classes of malformed input.

compiler/parse_type_repn.m:
    New module to parse type_repn items.

compiler/polymorphism.m:
    Make some predicates that operate on type constructors take
    the type constructors themselves as input arguments, not a whole type
    *using* that type constructor. Put the arguments of those predicates
    in a more standard order.

    Note that some predicates don't belong in this module.

compiler/special_pred.m:
    Make the code that decides whether a special predicate for a type
    constructor can be defined lazily avoid using type representation
    information. (Actually, we now make decisions about lazy vs eager
    definitions after type representation is available, but that was
    not so in an earlier version of this change, and the new code
    is more robust.)

compiler/unify_proc.m:
    When we decide to generate code for a compare predicate that needs
    the type to have an index predicate, don't presume that the index
    predicate has already been declared and defined; instead, declare
    and define it then and there. (Index predicates are *never* called
    from anywhere else.)

    Pack the information needed to define a special predicate
    into a single structure, to simplify the above.

    Since the creation of a clause for a compare predicate may now require
    the declaration and definition of an index predicate, the module_info
    field of the unify_proc_info is now a writeable field.

    Give some predicates and function symbols more meaningful names.

    Note some problems with the existing code.

compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_mode.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_solver.m:
compiler/check_typeclass.m:
compiler/code_info.m:
compiler/comp_unit_interface.m:
compiler/ctgc.selector.m:
compiler/ctgc.util.m:
compiler/default_func_mode.m:
compiler/det_report.m:
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/erl_code_gen.m:
compiler/export.m:
compiler/foreign.m:
compiler/get_dependencies.m:
compiler/goal_expr_to_goal.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_out_module.m:
compiler/inst_check.m:
compiler/inst_test.m:
compiler/inst_util.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_warn.m:
compiler/ml_accurate_gc.m:
compiler/ml_simplify_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mode_util.m:
compiler/modecheck_goal.m:
compiler/module_qual.collect_mq_info.m:
compiler/modules.m:
compiler/parse_item.m:
compiler/parse_pragma.m:
compiler/parse_tree.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
compiler/post_term_analysis.m:
compiler/proc_requests.m:
compiler/prog_item_stats.m:
compiler/qual_info.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/resolve_unify_functor.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/simplify_goal_ite.m:
compiler/stack_opt.m:
compiler/state_var.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/superhomogeneous.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/term_constr_build.m:
compiler/term_norm.m:
compiler/trailing_analysis.m:
compiler/type_constraints.m:
compiler/type_ctor_info.m:
compiler/typecheck.m:
compiler/unify_gen.m:
compiler/untupling.m:
compiler/unused_imports.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
    Conform to the changes above.

tests/invalid/Mmakefile:
    Disable the reserve_tag test case, as it is not applicable anymore.

tests/invalid/exported_foreign_enum.{m,err_exp}:
tests/invalid/pragma_qual_error.{m,err_exp}:
    Delete reserve_tag pragmas from these test cases, and its effects
    from the expected outputs.

tests/invalid/bad_foreign_type.err_exp:
tests/invalid/bigtest.err_exp:
tests/invalid/foreign_enum_invalid.err_exp:
tests/invalid/type_lhs_var.err_exp:
tests/invalid/uu_type.err_exp:
tests/invalid/where_abstract_enum.err_exp:
tests/invalid/where_direct_arg.err_exp:
    Expect the updated messages for some errors.

tests/valid/Mmake.valid.common:
tests/valid/Mmakefile:
    Disable any reserve_tag test cases, as they are not applicable anymore.
2018-01-31 17:54:40 +11:00
Zoltan Somogyi
d967f36545 Improve error messages about unexpected module names, again.
When you get this message, the error may be in the module name that it
reports to be wrong, but it may be in the places that set the compiler's
expectations of what the name of the module should be. This latter is
very likely the case when one moves a module of the Mercury compiler
from one package to another. In such cases, the problems are the old modules
that continue to refer to the renamed module by its old name.

This diff improves the error message by indicating *precisely* the locations
that refer to the old name, since these are the locations that establish the
expectation that is not met.

compiler/module_imports.m:
    Change the module_and_imports structure to record, for each imported
    or used module, and for each child module, the location of the relevant
    ":- import_module" or ":- include_module" declaration(s).

compiler/deps_map.m:
    When tracing references from module A to module B.C (either because
    A imports B.C, or because A = B and A includes C), record the location
    of the ":- import_module" or ":- include_module" declaration as a source
    of the expectation that any file that contains module C will have
    B.C as module C's fully qualified name. Since a module is usually imported
    by more than one other module, there may be several sources of such
    expectations.

compiler/parse_module.m:
    Change the wording of the error message to reflect the change in what
    the context denotes.

compiler/get_dependencies.m:
compiler/prog_item.m:
    When returning the sets of modules imported, used or included by some
    entities such as item blocks, return the contexts of those
    imports/uses/includes as well.

compiler/compile_target_code.m:
compiler/hlds_module.m:
compiler/make.dependencies.m:
compiler/make.module_dep_file.m:
compiler/make.program_target.m:
compiler/mercury_compile_main.m:
compiler/module_deps_graph.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/write_deps_file.m:
    Conform to the changes above.

tests/invalid/bad_module_name.err_exp:
    Expect the updated error message.
2017-12-12 13:47:14 +11:00
Zoltan Somogyi
1da267e9f0 Fix a bug in handling instances with --warn-unused-imports.
This fixes Mantis bug #412.

compiler/unused_imports.m:
    Consider that an instance declaration makes a module "used" only if
    it occurs in the module being compiled, not in an imported or ancestor
    module. (Mantis bug 412 was caused by instance declarations in implicitly
    imported modules.)

    Fixing #412 also exposed another bug. When computing the set of modules
    used by predicates, we considered (besides some non-type entities)
    only the types of the predicate's arguments, not the types of non-argument
    variables. In one case in the compiler (mmc_analysis.m), this lead to
    some actually-used modules not being marked as such, which lead to
    false unused-import warnings to be generated for them. Fix this by scanning
    the types of all variables in all of a predicate's procedures, not just
    the arguments.

    Improve the infrastructure for debugging similar problems.

    Note some possibilities for future improvement.

    Change a predicate name to fit the naming scheme.

compiler/analysis.m:
    Add an XXX about a possible improvement.

compiler/hlds_out_module.m:
    Make the output we generate for instance methods more readable.
    As part of this, fix an old bug in the printing of the instance table:
    the first line of the first method of each concrete instance declaration
    was accidentally commented out.

compiler/parse_tree_out.m:
    Export a different utility predicate for hlds_out_module.m. Make its name
    conform to the scheme used by related predicates.

browser/browse.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pred.m:
compiler/add_special_pred.m:
compiler/check_for_missing_type_defns.m:
compiler/check_promise.m:
compiler/exception_analysis.m:
compiler/handle_options.m:
compiler/inst_match.m:
compiler/mercury_to_mercury.m:
compiler/ml_tailcall.m:
compiler/module_qual.m:
compiler/op_mode.m:
compiler/parse_inst_mode_defn.m:
compiler/parse_tree_out_clause.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_out_inst.m:
compiler/parse_tree_out_pragma.m:
compiler/parse_tree_out_pred_decl.m:
compiler/parse_tree_out_term.m:
compiler/parse_type_defn.m:
compiler/parse_type_name.m:
compiler/parse_util.m:
compiler/parse_vars.m:
compiler/prog_ctgc.m:
compiler/recompilation.usage.m:
compiler/resolve_unify_functor.m:
compiler/term_constr_main.m:
compiler/term_constr_main_types.m:
compiler/write_deps_file.m:
library/bt_array.m:
    Delete unused imports.

compiler/module_qual.qual_errors.m:
    Import a module that the parent module_qual.m doesn't import anymore.

tests/warnings/bug412.{m,exp}:
    The test case for this bug.

tests/warnings/Mmakefile:
tests/warnings/Mercury.options:
    Enable the new test case.

tests/invalid/import_in_parent.err_exp:
    Update the expected output for this test case. The parent module
    does not use the imported module (bool) at all, so this is what the
    error message says after this diff, though its submodule does use bool.
2016-07-17 10:20:29 +02:00
Zoltan Somogyi
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.
2016-05-20 05:47:36 +10:00
Zoltan Somogyi
4ebc3ffa04 Carve four modules out of prog_data.m.
The prog_data.m module is imported by most modules of the compiler; by
359 modules out of 488, to be exact. Yet it has many parts that most of
those 359 modules don't need. This diff puts those parts into four new
modules. The number of imports of these modules:

    348 modules import prog_data.m
     84 modules import prog_data_foreign.m
     62 modules import prog_data_pragma.m
     12 modules import prog_data_event.m
      5 modules import prog_data_used_modules.m

compiler/prog_data_event.m:
compiler/prog_data_foreign.m:
compiler/prog_data_pragma.m:
compiler/prog_data_used_modules.m:
    New modules. They contain the parts of the parse tree that deal
    respectively with the specification of events and event sets,
    interfacing to foreign languages, pragmas, and the sets of used
    (i.e. not unused) modules.

compiler/prog_data.m:
    Delete the stuff that is now in the new modules. Put the remaining parts
    of the module into a logical order.

compiler/parse_tree.m:
compiler/notes/compiler_design.html:
    Include and document the new modules.

compiler/globals.m:
    Move a type here from prog_data.m, since this is where it belongs.

compiler/add_foreign_proc.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma.m:
compiler/add_solver.m:
compiler/add_trail_ops.m:
compiler/call_gen.m:
compiler/code_gen.m:
compiler/code_loc_dep.m:
compiler/comp_unit_interface.m:
compiler/compile_target_code.m:
compiler/complexity.m:
compiler/continuation_info.m:
compiler/coverage_profiling.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.livedata.m:
compiler/ctgc.selector.m:
compiler/deep_profiling.m:
compiler/dep_par_conj.m:
compiler/deps_map.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/elds_to_erlang.m:
compiler/equiv_type.m:
compiler/erl_call_gen.m:
compiler/exception_analysis.m:
compiler/export.m:
compiler/fact_table.m:
compiler/foreign.m:
compiler/frameopt.m:
compiler/get_dependencies.m:
compiler/goal_form.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/hlds_goal.m:
compiler/hlds_module.m:
compiler/hlds_out_goal.m:
compiler/hlds_out_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_pred.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/ite_gen.m:
compiler/item_util.m:
compiler/jumpopt.m:
compiler/layout.m:
compiler/layout_out.m:
compiler/live_vars.m:
compiler/livemap.m:
compiler/llds.m:
compiler/llds_out_file.m:
compiler/llds_out_global.m:
compiler/llds_out_instr.m:
compiler/make.dependencies.m:
compiler/make.module_dep_file.m:
compiler/make_hlds.m:
compiler/make_hlds_warn.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/ml_call_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_proc_gen.m:
compiler/ml_tailcall.m:
compiler/ml_unify_gen.m:
compiler/mlds.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/modecheck_goal.m:
compiler/module_imports.m:
compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
compiler/modules.m:
compiler/opt_debug.m:
compiler/par_conj_gen.m:
compiler/parse_pragma.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_out_pragma.m:
compiler/pd_cost.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/proc_gen.m:
compiler/prog_ctgc.m:
compiler/prog_event.m:
compiler/prog_foreign.m:
compiler/prog_item.m:
compiler/prog_out.m:
compiler/prog_util.m:
compiler/purity.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.points_to_graph.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_scope.m:
compiler/simplify_proc.m:
compiler/smm_common.m:
compiler/stack_layout.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.domain.m:
compiler/structure_reuse.indirect.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_initial.m:
compiler/term_constr_main.m:
compiler/term_constr_main_types.m:
compiler/term_constr_pass2.m:
compiler/term_constr_util.m:
compiler/term_errors.m:
compiler/term_pass1.m:
compiler/term_pass2.m:
compiler/term_traversal.m:
compiler/term_util.m:
compiler/termination.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/type_constraints.m:
compiler/typecheck.m:
compiler/unique_modes.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/use_local_vars.m:
compiler/write_deps_file.m:
    Conform to the changes above.
2016-03-13 18:19:31 +11:00
Zoltan Somogyi
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
2016-02-09 13:50:37 +11:00
Zoltan Somogyi
5649f36c80 Handle "use_module in interface, import_module in implementation".
If a module m1 imports module m2 using a use_module declaration in its
interface section but also imports it using an import_module declaration
in its implementation section, then references to entities defined in m2
in the interface of m1 must be module qualified, but similar references
in the implementation of m1 need NOT be module qualified.

The Mercury compiler has long had a bug that allowed entities imported
in the implementation of module m1 to be used in the interface of m1,
against the rules of the language. When I fixed that bug on 2015 nov 11,
the compiler became unable to properly process the situation described
in the paragraph above, because it still had another bug, which was that
it had a single setting for module qualification requirements: either it
was required *everywhere* in m1, or it was required *nowhere* in m1.
This diff fixes that bug (mantis bug 401) by allowing different requirements
in this respect in the interface of m1 versus its implementation.

It also changes the de-facto meaning of what exactly a use_module declaration
requires. The reference manual says only:

    Uses of entities imported using @code{use_module} declarations
    @emph{must} be explicitly module qualified.

This WAS unambiguous when it was written in june 1997, a few months before
submodules were added to the language. With a flat module system, there were
no nested module names, so either the module name was present, or it wasn't.
In the presence of nested modules, though, it IS ambiguous: HOW MUCH of
the module name must be present? The reference manual is silent on this.

At the moment, in the presence of a use_module for module ma.mb.mc,
a predicate p1 in ma.mb.mc may of course be referred to as ma.mb.mc.p1,
but may also be referred to as mb.mc.p1, or even just mc.p1. The specification
of mc is always required, but exactly WHICH of the previous module name
components are required depends on whether e.g. ma or ma.mb were themselves
imported via use_module or import_module declarations. The code implementing
the check (find_matches_in_permissions_map in module_qual.id_set.m) is itself
not too clear.

This diff changes the rules so that all references to anything imported
via a use_module declarations have to be fully qualified. This is stricter
than the existing rule, but it is MUCH simpler, and it better matches
the original intent of use_module declarations, which is the avoidance
of ALL POSSIBILITY of ambiguity.

NEWS:
doc/reference_manual.texi:
    Document this change to the language.

compiler/prog_item.m:
    Change the representation of sections in .int* files. Previously,
    we recorded whether the interface file that the section was from
    was read for an `import_module' or a `use_module' declaration.
    We now allow the recording of the fact that it had both declarations,
    a use_module in the interface and an import_module in the implementation.

compiler/modules.m:
    Treat modules that have both a `use_module' declaration in interface
    and an `import_module' declaration in the implementation as being of this
    new internal section kind.

    Add some infrastructure for debugging similar problems in the future.

compiler/module_qual.id_set.m:
    Change the permissions system. Instead of recording *independently*
    whether (a) an entity may be used in the interface and (b) whether
    references to it must be qualified, record *separately* whether
    (a) it may be used in the interface, and if so with what qualification
    requirements, and (b) what its qualification requirements are in the
    implementation. Unlike the old permission setup, the new one allows us
    to express the "use_module in interface, import_module in implementation"
    situation.

    Implement the change to the language, by requiring full module
    qualification of entities imported via use_module declarations.
    This allows us to use a single parameterized piece of code to handle
    both unqualified and qualified references, whereas before we used
    separate pieces of code for them.

    Change the way we handle errors in module qualification. Instead of
    looking only for precise matches only, and looking for the possible causes
    of errors only if we find either no matches or two or more matches, we now
    return the near-miss matches as well, the ones that we need to decide
    on what error message we want to generate. While this is slightly slower,
    it is *much* simpler, since it allows us to avoid duplicating the search
    code: once for precise matches only, once for no-match errors, and once
    for multiple-match errors.

compiler/module_qual.collect_mq_info.m:
    Set permissions for symbol access according to the new permissions system.
    Code that previously triggered the bug will use the new interface file
    section kind, and can now have its permissions record correctly.

compiler/module_qual.qual_errors.m:
    Use a single predicate to generate error messages for all situations
    in which there is not a single precise match for a module qualification.
    This allows us to diagnose multiple potential problems with a single
    lookup.

    Change the wording of an existing error message to avoid a possibly-untrue
    implication.

compiler/hlds_data.m:
    Rename a field of the type_defn type to better document its meaning.

compiler/make_hlds.m:
    Document the meaning of the need_qualifier field in sec_infos.

compiler/add_type.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.m:
compiler/pred_table.m:
compiler/parse_tree_out.m:
compiler/prog_item_stats.m:
    Conform to the above changes.

mdbcomp/sym_name.m:
    Add a utility predicate for use in looking for near-miss matches
    in module qualification.

    Make the documentation of a related predicate more precise.

tests/invalid/bad_instance.m:
tests/submodules/class.m:
tests/submodules/nested.m:
tests/submodules/nested3.m:
tests/submodules/parent.m:
    Make names fully module qualified where the language rules now require it.

tests/submodules/deeply_nested.m:
    Comment out a part of the test that tested the partially qualified names,
    since these are now not allowed.

tests/invalid/errors.err_exp:
    Expect a now-improved error message.

tests/invalid/test_nested.err_exp:
tests/invalid/transitive_import.err_exp:
tests/invalid/undef_type.err_exp:
    Expect a now less-likely-to-mislead error message.

tests/valid_seq/int_impl_imports.m:
tests/valid_seq/int_impl_imports_2.m:
    The test case for mantis bug 401.

tests/valid_seq/Mmakefile:
    Enable the new test case.
2016-01-11 23:05:39 +11:00
Zoltan Somogyi
5ade3715ea Add the compiler option --warn-interface-imports-in-parents.
When enabled, this asks the compiler to apply the same rules to parent
modules as it does to every other module, and generate warnings for any
import in the interface of a module if that import is not used in the interface
of that module. By default, we still supress all such warnings on the basis
that a module A imported in the interface of module B may be used in the
interface of module B.C even if it isn't used in B itself, but this option
provides a way to override that presumption.

compiler/options.m:
doc/user_guide.texi:
    Add the option.

compiler/module_qual.qualify_items.m:
    If this option is set, then don't set to empty the set of not-yet-seen-
    to-be-used imports when we see an include_module declaration.

compiler/module_qual.m:
    Add a field to the mq_info (actually, its rarely used part, mq_sub_info)
    that says whether the option is set, for module_qual.qualify_items.m
    to use.

compiler/module_qual.m:
compiler/module_qual.qual_errors.m:
    Have module_qual.m implement the --warn-interface-imports option
    just once, to save having module_qual.qual_errors.m having to implement
    it once per unused module.
2015-11-21 21:41:26 +11:00
Mark Brown
b2ae55c29c Change 'none' to 'none_or_default_func' in ho_inst_info.
This value of ho_inst_info is used for first-order values as well as
for functions that have the default inst, and the new name better
reflects that.

Places using this value have been checked for correctness. Issues that
need to be looked at have been marked with XXX, although have not been
addressed in this change.

compiler/prog_data.m:
	Update the type.

compiler/inst_match.m:
	Add XXX comments. This module needs to check for non-default
	function insts in a bunch of places.

compiler/inst_util.m:
	Add XXX comments. We lose information about non-default function
	insts when merging bound and any. The information needs to be
	either preserved or disallowed entirely.

compiler/float_regs.m:
	Add XXX comments. This module may miss cases involving default
	function insts.

compiler/modecheck_unify.m:
	Add XXX comment. We should exclude pred and non-default func
	lambda non-locals from becoming locked, an addition to default
	functions.

compiler/*.m:
	No special handling is required for other modules.
2015-11-16 21:13:04 +11:00
Zoltan Somogyi
9fe11c2f8e Delete some redundant imports. 2015-11-16 19:23:11 +11:00
Zoltan Somogyi
cc9912faa8 Don't import anything in packages.
Packages are modules whose only job is to serve as a container for submodules.
Modules like top_level.m, hlds.m, parse_tree.m and ll_backend.m are packages
in this (informal) sense.

Besides the include_module declarations for their submodules, most of the
packages in the compiler used to import some modules, mostly other packages
whose component modules their submodules may need. For example, ll_backend.m
used to import parse_tree.m. This meant that modules in the ll_backend package
did not have to import parse_tree.m before importing modules in the parse_tree
package.

However, this had a price. When we add a new module to the parse_tree package,
parse_tree.int would change, and this would require the recompilation of ALL
the modules in the ll_backend package, even the ones that did NOT import ANY
of the modules in the parse_tree package.

This happened even at one remove. Pretty much all modules in every one
of the backend have to import one or more modules in the hlds package,
and they therefore have import hlds.m. Since hlds.m imported transform_hlds.m,
any addition of a new middle pass to the transform_hlds package required
the recompilation of all backend modules, even in the usual case of the two
having nothing to do with each other.

This diff removes all import_module declarations from the packages,
and replaces them with import_module declarations in the modules that need
them. This includes only a SUBSET of their child modules and of the non-child
modules that import them.
2015-11-13 15:03:20 +11:00
Zoltan Somogyi
df794c259a Break up module_qual.m into cohesive submodules.
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.id_set.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
    The new submodules of module_qual.m.

compiler/module_qual.m:
    Delete the stuff moved to the new submodules.

compiler/notes/compiler_design.html:
    Document the new submodules.
2015-11-12 01:25:09 +11:00
Zoltan Somogyi
e0a430c476 Put the contents of module_qual.m into a logical order.
compiler/make_hlds_passes.m:
    Group related predicates together. Document the groups.
    Rename some predicates to reflect their membership of their group.

    Separate the flags about undefined types and typeclasses, and about
    undefined insts and modes.

    Replace several uses of bools (including those flags) with bespoke types.

    Replace some lambdas with named predicates.

    Inline some predicates in their only caller.

compiler/mercury_compile.m:
compiler/module_qual.m:
compiler/write_module_interface_files.m:
    Conform to the changes above about undefined types etc.
2015-11-11 18:55:08 +11:00
Zoltan Somogyi
f204a6147b Speed up module_qual.m.
compiler/module_qual.m:
    Optimize the processing of include_module, import_module and use_module
    declarations, by taking out the relevant fields out of mq_info just once
    per section, not once per declaration, and putting it back just once
    as well.

    Inline the single-use predicates that used to process these declarations.

    Move the infrequently used fields of mq_info into mq_sub_info,
    leaving mq_info with 8 fields, to avoid wasting space with Boehm gc.

    Try to avoid updating mq_info if the field we operated on didn't actually
    change as a result of that operation.

    When inserting a new mq_id into an id_set, most of the time,
    the relevant submap won't be there, so optimize for this common case
    by avoiding a search for it.
2015-11-11 15:24:23 +11:00
Zoltan Somogyi
0821b301f2 Require that types/insts/modes in interfaces be defined in the interface.
compiler/module_qual.m:
    The interface of a module A contains items (e.g. predicate declarations)
    that refer to entities such as types, insts, modes etc. They may refer
    to those entities if (a) they are defined in the interface of module A,
    (b) in a parent module of module A, or (c) if they are imported from
    another module, module B, which is imported into module A in the interface
    of module A.

    The old algorithm that attempted to enforce this requirement had a basic
    design fault: it based the decision as to whether the use of an entity
    in the interface was legal solely on the name of the module that defined
    that entity. This correctly implements tests (b) and (c), but it does
    not even attempt to implement the interface test part of (a).
    It therefore allowed exported items to refer to nonexported entities.

    This diff changes the whole design approach to the test. Instead of
    keeping a list of modules *all* of whose entities may be used in the
    interface of the current module, record for *every* entity whether
    it may be used in the interface. Set the permissions differently
    in the interface and implementation sections of the current module.

    Improve the formatting of the ambiguity error message.

NEWS:
    Announce the stricter enforcement of the documented language rules,
    in a new section for potentially compatibility-breaking changes.

compiler/check_typeclass.m:
    Delete a test for a special case of the situation that module_qual.m
    now tests for. If this problem occurs, module_qual.m will pick it up,
    and check_typeclass.m will never even be invoked, so this copy of the test
    can never succeed.

library/hash_table.m:
    Fix code that violated the language rules: we export a type that
    includes another type, but didn't export the second type. We now do.

browser/declarative_analyser.m:
browser/declarative_edt.m:
compiler/coverage_profiling.m:
    Fix code that violated the language rules. We used to export predicates
    and functions whose argument types included nonexported types. As it
    happens, none of those predicates and functions actually need to be
    exported, so keep them private.

    In coverage_profiling.m, don't abstract export a type that is not
    used outside the module, and give a function a name that doesn't
    clash with a type name.

tests/invalid/bug17.{m,err_exp}:
    A new test case to test the error message we get if the module interface
    refers to a nonexported type.

tests/invalid/bad_instance.err_exp:
    This test case used to get two kinds of errors, one of which was
    the illegal use of nonexported type in an exported abstract instance
    declaration. We now discover this error earlier, and stop after we
    do so. Update the expected error message.

tests/invalid/bad_instance2.{m,err_exp}:
    New test case: a modified copy of bad_instance.m, testing the other
    kind of error originally tested by bad_instance.m.

tests/invalid/instance_no_type.err_exp:
    Update the expected error message.

tests/invalid/Mmakefile:
    Enable the new test cases.

tests/benchmarks/query.m:
tests/hard_coded/unused_float_box_test.m:
tests/valid/bug300.m:
tests/valid/deforest_bug.m:
tests/valid/higher_order4.m:
tests/valid/lambda_recompute.m:
tests/valid/mert.m:
tests/valid/reuse_static.m:
tests/valid/switch_detection_bug2.m:
tests/valid/time_yaowl.m:
tests/warnings/unused_args_test.m:
    Fix code that violated the language rules, typically by exporting
    the type that previously, we illegally used in the module interface.

tests/recompilation/add_type_re.err_exp.2:
    Expect the updated ambiguity error message.
2015-11-11 14:28:57 +11:00
Zoltan Somogyi
9e01e8da4a Improve error messages for bad insts in mutables.
compiler/add_mutable_aux_preds.m:
compiler/hlds_code_util.m:
    Move the code that tests the insts in mutables to see if they are allowed
    in mutables from hlds_code_util.m to add_mutable_aux_preds.m, since that
    code is not a generally useful utility.

    Change that code so that instead of generating the same error message
    ("this is not a valid inst for a mutable") for all errors, we now
    (a) generate a separate error message for each problem in the inst, and
    (b) generate a message that is specific to the error, for each such
    error.

compiler/prog_item.m:
    Record two insts for each mutable, not one. The two differ in that
    one is processed by equiv_type.m, the other isn't. If possibly,
    add_mutable_aux_preds.m generates error messages from the latter,
    because it preserves the original structure of the inst. This is
    important, because having the compiler complain about e.g. a "unique"
    inst in a mutable is confusing if the inst in the mutable is just "i1".
    You want the error message to explain that "unique" is part of the
    expansion of "i1", and this can only be done if the test works on an inst
    in which equiv_type.m hasn't replaced "i1" with its definition.

    Record two types for each mutable, not one, with the same difference,
    for the same reason, for use by future checks on types in mutables.

    Put the fields of item_mutable_infos into a more logical order.

compiler/equiv_type.m:
    Process only one of each pair of type and inst fields in
    item_mutable_infos.

compiler/get_dependencies.m:
compiler/module_qual.m:
compiler/parse_tree_out.m:
compiler/prog_io_mutable.m:
compiler/recompilation.version.m:
compiler/write_module_interface_files.m:
    Conform to the change in prog_item.m.

tests/invalid/bad_mutable.err_exp:
tests/invalid/user_mutable.err_exp:
    Expect the improved error messages.
2015-11-09 15:10:00 +11:00
Peter Wang
538919de26 Make some compiler predicates tail recursive with LCMC.
This prevents the compiler exhausting the stack on larger modules.

compiler/module_qual.m:
compiler/purity.m:
compiler/typecheck.m:
	Make the LCMC opportunities more obvious to programmers
	maintaining the code.

compiler/Mercury.options:
	Enable --optimize-constructor-last-call for the preceding
	modules.
2015-10-16 15:03:03 +11:00
Zoltan Somogyi
0da23e02c5 Add syntax for saying what type an inst is for.
As agreed on the developers mailing dist, this syntax is

:- inst i(...) for tc/n
    --->    f1(...)
    ;       f2(...)
    ...
    ;       fn(...).

It also works on the equivalent syntax

:- inst i(...) for tc/n == bound(...).

The type constructor may be specified only for insts that are being
defined to be equivalent to bound insts, since only for these can we
check that the top level function symbols belong to the specified type
constructor.

There is no documentation of the new language extension yet, since it is
not yet really useful. That would come later, when we check that an inst
specified as for being for a specific type is used only on values
of that type. We would also need to resolve the two issues marked with
"XXX IFTC" in the diff.

compiler/prog_item.m:
    Add a field to the parse tree representation of inst definitions
    to record the absence or presence of the "for type" type constructor.

compiler/hlds_data.m:
    Modify the representation of inst definitions to allow recording
    the fact that an inst is declared to be for a specified type constructor,
    to allow recording the presence of an error in this regard (the inst
    is not for the type, or the inst is exported to places where the type
    is not visible). Differentiate between no type constructor being associated
    with the type because (a) it would not make sense, and (b) it would make
    sense, but no type constructor was specified. (After type-constructor-
    specific insts have been in the language long enough, we may want to
    generate a warning or even an error for the latter.)

library/ops.m:
    Add "for" as an operator, as discussed on the mailing list.

NEWS:
doc/reference_manual.texi:
    Announce and document the new operator.

compiler/prog_io_mode_defn.m:
    Parse the new bit of syntax.

    Give a predicate a more meaningful name.

compiler/parse_tree_out.m:
    Output the new piece of syntax in inst definitions if needed.

compiler/add_mode.m:
    When adding an inst defn in the parse tree to the HLDS, record the
    absence or presence of the "for type" type constructor, and if it is
    absent, whether it would have made sense for one to be present. Generate
    an error message if one is present when it doesn't make sense for it to be
    present.

compiler/equiv_type.m:
    Note that we should expand the type constructors in inst defns,
    and note a related issue that is probably a very old bug.

compiler/inst_check.m:
    For insts that are declared to be a specific type constructor, don't
    check whether there is SOME type constructor they are compatible with.
    Check whether they are compatible with their declared type, and if they
    aren't, generate an error, not a warning.

compiler/module_qual.m:
    Module qualify any type constructors in inst definitions.

compiler/inst_user.m:
compiler/intermod.m:
compiler/prog_io_util.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.

tests/dppd/grammar_impl.m:
    Protect a function symbol named "for" against being considered an operator.

tests/invalid/bad_inst_for_type.{m,err_exp}:
    A new test case, to see whether we get the expected set of error messages
    for incorrect use of the new language extension; no more, and no less.

tests/invalid/Mmakefile:
    Enable the new test case.
2015-10-04 18:06:33 +11:00
Zoltan Somogyi
003bc5c795 Don't make an error message misleading.
compiler/module_qual.m:
    When we find an undefined type with a module-qualified name, we want
    to generate a message about the specified module name not being imported
    if it isn't imported. However, we insisted on an exact match of the
    name of an imported module, when a partially specified module name
    will match as well. Fix this, so that we don't generate a message of the
    form "module x isn't imported" when module y.x IS imported.
2015-09-25 15:09:06 +10:00
Zoltan Somogyi
b68abc9be7 Use a kind-specific status type for insts and modes.
compiler/status.m:
    Change the inst_status and mode_status types so that instead of just
    being synonyms for old_import_status, they are now a pair of an
    old_import_status and a new type, new_instmode_status, which should
    eventually become the status type for insts and modes (hence the name).

    Delete the unused operations on inst_statuses and mode_statuses.
    For the rest, modify them so that they are done on both the
    old_import_status half and the new_instmode_status status half,
    and abort if they get different answers.

compiler/hlds_out_module.m:
    Print out the status of each inst and mode in HLDS dumps,
    if the inst table and mode table are being dumped.

compiler/prog_item.m:
    Rename import_locn_ancestor to import_locn_import_by_ancestor,
    since this prevents ambiguity: the former can be interpreted to mean
    that the imported module is an implicit-imported ancestor.

compiler/add_mode.m:
compiler/hlds_out_util.m:
compiler/intermod.m:
compiler/make_hlds_passes.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/xml_documentation.m:
    Conform to the changes above, duplicating and cross-checking
    each operation as needed.
2015-09-20 13:36:06 +10:00
Zoltan Somogyi
ea094b5bb7 Make the import_status type part of the HLDS.
The import_status type was defined in parse_tree.status.m, but it is
not actually used in the parse_tree package. It is used, extensively,
in the hlds package.

compiler/status.m:
compiler/prog_item.m:
compiler/prog_data.m:
    Move the parts of status.m that *are* needed in the parse_tree package
    to modules in that package. The section markers and the import_locn type
    are moved to prog_item.m, while the need_qualifier type is moved to
    prog_data.m.

compiler/parse_tree.m:
compiler/hlds.m:
    Switch the status.m module from being in the parse_tree package
    to being in the hlds package.

compiler/notes/compiler_design.html:
    Document the switch.

compiler/*.m:
    Update import_module declarations as needed after the above change.

    In some places, import parse_tree.prog_item as well as hlds.status,
    even if we are only intested in statuses, because the import_locn type,
    which part of some statuses, *is* used in the parse_tree package,
    and must therefore be defined there. These undesirable dependencies
    will go away when we implement the proposal for purpose-specific status
    types.
2015-09-09 01:47:08 +10:00
Zoltan Somogyi
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.
2015-08-25 00:38:49 +10:00
Zoltan Somogyi
82d3141334 Fix the context of unused import_module error messages.
compiler/module_qual.m:
    When printing error messages about modules imported in the interface
    but not used in the interface, we used to use the context of the module's
    `:- module' declaration, not the context of the bad `:- import_module'
    declarations themselves. Fix that, by generating a separate error message
    for each unnecessarily interface-imported module, each with its own
    context.

tests/invalid/bug113.err_exp:
tests/warning/unused_import.exp:
tests/warning/unused_interface_import.exp:
    Update the context (and the wording) of the expected error message.
2015-08-12 22:14:37 +10:00
Zoltan Somogyi
c50b5a23f8 Improve module_qual.m.
Rewrite the comment describing the purpose of the module, in order to

- update the description of what it module qualifies, since it was not modified
  when the code was modified a long time ago when typeclasses were added,
- explain what it does NOT module qualify, and why,
- outline the algorithm it follows.

Simplify the code handling promise goals by using accumulators.

Remove an unnecessarily general predicate.
2015-08-12 20:39:54 +10:00
Zoltan Somogyi
ef44f50bee Eliminate the old module_defn item.
After my earlier changes to the item list, we used module_defns for only
two things: recording when one module includes another, and recording
when one module imports or uses another. After this diff, both those
pieces of information are stored separately in each item block.
This has two benefits.

The first benefit is that it allows us to use the type system to enforce
structural invariants about where include_module, import_module and use_module
declarations may appear. The one invariant that we now enforce is that
optimization files may not contain either include_module or import_module
declarations, though they may contain use_module declarations. I suspect that
there are also similar invariants about interface files, but finding them
requires something like this change.

The second benefit is that it allows traversals of item blocks to scan
only the part of the item block that may contain the object of interest.
While reading in interface and optimization files, we used to scan the
full item list several times to find included and imported modules; those
scans can now look at just the relevant information. Since the item lists
that need to be processed usually include all the declarations in a
substantial number of other modules, including some (such as list.m) that
have LOTS of declarations, the speedup can be substantial. On tools/speedtest,
the speedup is 1.5%.

compiler/prog_item.m:
    Make the change described above.

    Provide utility predicates on the new types representing include_module,
    import_module and use_module declarations.

    Move an old utility predicate from here to prog_io.m, since only prog_io.m
    uses it.

compiler/module_imports.m:
    Several fields of the module_imports type contained sets of module names,
    but stored them as lists. Change these to actual sets, to distinguish them
    from the lists whose order is actually important. (Basically, the order
    of processing .trans_opt files is important, but the order in which
    we read in .int0, .int3, .int2, .int and .opt files isn't.) In several
    places, this also avoids the need for conversions of lists to sets
    for set operations, and then back to lists.

compiler/modules.m:
    This module had several predicates that processed list of module names.
    Make these operate on sets of module names instead, and break each of them
    into two predicates: one that decides whether there is a next module name,
    and if yes whether it has been processed already, and one to do the actual
    processing if needed. This avoid the need for excessive indentation.

    The code that discovers what other modules' interface files may need
    to be read is now simpler due to the updated item_block structure.

    Remove the submodule whose job it was to discover what modules are included
    in items or item blocks, since that task has now become trivial, and is
    now done by a utility predicate in prog_item.m. Since this was the second
    last submodule (of the original eight), the last submodule is now the
    whole module. Therefore this module now has significantly greater cohesion
    than it had before.

compiler/write_module_interface_files.m:

compiler/prog_io_item.m:
    Parse include_module, import_module and use_module declarations as
    markers, not as items.

compiler/prog_io.m:
    Expect include_module, import_module and use_module declarations as
    markers, not as items.

compiler/split_parse_tree_src.m:
    Discover included submodules more simply with the updated item_block
    structure.

compiler/compile_target_code.m:
    Put the arguments of the predicates in this module in a more standard
    order.

compiler/recompilation.version.m:
    Conform to the above changes. Note a possible bug.

    Use a bespoke type to replace some bools.

compiler/check_raw_comp_unit.m:
compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/generate_dep_d_files.m:
compiler/get_dependencies.m:
compiler/hlds_module.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make.dependencies.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_to_mercury.m:
compiler/module_deps_graph.m:
compiler/module_qual.m:
compiler/prog_io_find.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/trans_opt.m:
compiler/write_deps_file.m:
    Conform to the above changes.

mdbcomp/sym_name.m:
    Provide a utility predicate to get the set of ancestors of a module
    as a set as well as a list.

tests/invalid/exported_unify3.err_exp:
tests/invalid/ii_parent.ii_child.err_exp:
    Update the expected error messages, which refer to line numbers in
    .int0 files, which have now changed, as we now put all import_module
    declarations before ordinary items.

    (Error messages shouldn't refer to automatically generated files,
    but that is a separate concern.)
2015-08-11 21:56:01 +10:00
Zoltan Somogyi
a063679bc8 Simplify the use of statuses during module qualification.
compiler/module_qual.m:
    We used to store an mq_import_status in the mq_info. This was used
    for two separate purposes.

    - For module qualifications of types, typeclasses, insts and modes
      in the interface of a module, we record that the module that defines
      the type, typeclass, inst or mode is actually used in the interface,
      so we don't generate a warning about "module imported in the interface
      is not used in the interface". For this, the only distinction
      we care about is "in the interface" vs "not in the interface".

    - In some cases, we do need to know in what kind of module section
      the import took place, such as whether it is from the .int0 file
      of an ancestor, so we can e.g. record it as not being subject to
      warnings such as the one above.

    The vast majority of the code in module_qual.m needed an mq_import_status
    only for the first purpose. (The info is needed only at the bottom of the
    call graph, but has to be passed through lots of predicates to get there.)
    Only the handling of :- import_module declarations and decisions about
    the visibility of a few kinds of items requires knowing the kind of
    the surrounding section, and these are all near the top of the call graph.

    We now separate the two purposes, giving each its own type. The new
    mq_in_interface type records the distinction needed for the first purpose
    above, while the other "new" type, mq_section, is a rename of the old
    mq_import_status type, but with more purpose-specific names.

    Values of these two types are now passed explicitly to the predicates
    that need them, so that we cannot get situations where a stale,
    not-properly-updated status is used to make decisions.

    Similarly, pass the need_qualifier flag around explicitly to the places
    that need it (most don't).

    Put the argument lists of many predicates into a more logical order.

    Put the remaining fields of the mq_info into a more logical order,
    grouping related fields together. Put the field access predicates'
    declarations and clauses in the same order.

    Move the definition of the mq_info type next to its initialization
    predicate, as we do for pretty much every similar type.

    Avoid redundant tests of the section type when processing import_module
    declarations. Replacing three if-then-elses with one switch makes explicit
    that all the possible section types are properly handled.

compiler/make_hlds_passes.m:
    Don't set the need_qualifier flag in the mq_info during pass 3,
    since (a) it doesn't exist there anymore, and (b) we never needed it
    during pass 3 in the first place.

compiler/add_clause.m:
compiler/qual_info.m:
compiler/superhomogeneous.m:
    Conform to the above changes.
2015-08-05 18:04:53 +10:00
Zoltan Somogyi
c6521f9ec5 Store version number info separately from items.
We used to store such information in md_version_number module_defns
in the item list. This did not enforce the invariants we want for
version number records, which are that

    - they can appear only in interface files, not source or optimization
      files;

    - only one such record can appear in each interface file; and

    - there cannot be more than one such record for any given module
      in any augmented compilation unit (which can contain information from
      many interface files).

This change removes the md_version_number module_defn, and replaces it
with (a) a slot in the parse tree of interface files that may contain
the version number record of that module, and (b) a slot in augmented
compilation units that maps module names to the version number record
for the named module.

compiler/prog_item.m:
    Make the change above.

compiler/recompilation.m:
    Provide a type for mapping module names to the named module's version
    number record.

compiler/prog_io_item.m:
    Parse version number records not as items, but as a new kind of marker.

compiler/prog_io.m:
    Process this new marker. Record the first one in interface files.
    Generate error messages for any later records in any given interface file,
    or for any such records at all in any file of any other kind.

    Since the contents of interface files are automatically generated,
    users should never see the first of these kinds of messages.
    They should never see the second of these kinds of messages either,
    unless they hand-write a version number record, which is actually
    pretty hard to do, not least since the format is undocumented :-(

compiler/make_hlds_passes.m:
    Process the version number records separately from the items, since
    they are now stored separately.

compiler/module_imports.m:
    Provide a mechanism for collecting version number information
    as interface files are read in.

compiler/modules.m:
    Use that mechanism, and collect version number information
    as interface files are read in.

compiler/recompilation.check.m:
compiler/recompilation.version.m:
    Get the version number information these modules work with from the
    new slot in parse_tree_ints.

compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/hlds_module.m:
compiler/make.module_dep_file.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/read_modules.m:
compiler/split_parse_tree_src.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.
2015-08-02 04:20:04 +10:00
Zoltan Somogyi
fef26b8d4d Improve error messages for arity mismatches.
compiler/module_qual.m:
    One of the main data structures of this module maps a symname and arity
    to the set of modules that define an entity (type, inst, mode or typeclass)
    with that symname and arity. The representation of this data structure
    used to be a simple map from a symname and arity pair. Change this to
    a two-stage map, first from symname, and then from the arity.

    When we generate an error message because we found no match for a given
    symname and arity, use the new ability to search on symname alone
    to list the other arities (if any) for which there DO exist matches.

    The two-stage map should also be slightly faster than the old one-stage
    map, because we don't have to go through the comparison predicate for pairs
    to compare the symnames. However, any speedup is lost in the noise.

    Replace a pair with a bespoke type.

    Put some predicates' arguments into a more logical order.

    Give some variables more standard names.

tests/invalid/wrong_type_arity.{m,err_exp}:
    New test case to test the updated error message.

tests/invalid/Mmakefile:
    Enable the new test case.
2015-08-01 05:39:28 +10:00
Zoltan Somogyi
2856408ab0 Separate the different kinds of sections in aug_comp_units.
When we create augmented compilation units, the item blocks in that
augmented unit come from five sources:

- the original raw compilation unit, containing the source code of a module;
- the interface files of the modules directly imported by that module;
- the interface files of the modules indirectly imported by that module;
- the optimization files needed by that module; and
- the interface files needed by those optimization files.

Change the representation of augmented compilation units so that instead of
containing one list of item blocks, each of which had a general section type,
it now has five lists of item blocks, one for each category above, with
a section type specialized to the category.

After this change, the compiler can process just the item blocks it wants
to process, instead of having to process all the item blocks, all the while
filtering out the irrelevant blocks. This filtering used to be order dependent,
with the ams_transitively_imported section marker, which derived from the old
md_transitively_imported module_defn, marking the dividing line between
the first and second categories on the one hand and the third, fourth and fifth
categories on the other hand. That marker is now gone, and the item blocks
in each category have no need to be in a specific order.

compiler/prog_item.m:
    Make the above change in the representation of the augmented compilation
    unit.

compiler/module_imports.m:
    Instead of recording one list of item blocks for the augmented compilation
    unit being built, record five.

compiler/modules.m:
    Instead of always adding new item blocks to the one list, add it to the
    relevant list. For modules.m, this will be one of the three item block
    lists for interface files.

    Provide a mechanism for getting back the augmented compilation unit
    whole, once its building has finished.

compiler/intermod.m:
compiler/trans_opt.m:
    Instead of always adding new item blocks to the one list, add it to the
    relevant list. For intermod.m and trans_opt, this will be the item block
    list for optimization files.

compiler/status.m:
    Change the section types to account for the new kinds of sections
    in augmented compilation units (from source, interface and optimization
    files respectively).

    Besides recording which module the item blocks in interface and
    optimization sections came from, record the int_file_kind or opt_file_kind
    as well. The compiler does not use this extra information (yet); I am
    adding it so that I can look for further invariants.

compiler/file_kind.m:
    A new module carved out of prog_item.m, containing the types that define
    kinds of source, interface and optimization files, and the predicates that
    operate on them. This needs to be a new module, because (a) status.m now
    needs access to file kinds, (b) status.m should not import prog_item.m,
    since that would lead to circular imports, and (c) the file kinds
    don't belong with statuses.

compiler/parse_tree.m:
compiler/notes/compiler_design.html:
    Mention the new module.

compiler/equiv_type.m:
    Conform to the changes above.

    Replace the eqv_type_location type with the maybe_record_sym_name_use type,
    since the location (in this module's interface, in this module's
    implementation, in some other module) matters only for recording the uses
    of sym_names.

compiler/make_hlds_passes.m:
    Process all five lists of item blocks in each of the three passes.
    Note cases where this may not be needed.

compiler/module_qual.m:
    Conform to the changes above. Module qualify only the items in this
    module, not the items we got from other modules.

compiler/comp_unit_interface.m:
compiler/deps_map.m:
compiler/hlds_module.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/mercury_to_mercury.m:
compiler/split_parse_tree_src.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.
2015-07-31 16:54:06 +10:00
Zoltan Somogyi
011149bd0a Carve get_dependencies.m out of module_imports.m.
The entry for module_imports.m in compiler_design.html used to say this:

    module_imports.m contains the module_imports type and its access
    predicates, and the predicates that compute various sorts of
    direct dependencies (those caused by imports) between modules.

The predicates that compute those direct dependencies are used not just by
module_imports.m, but also by some other modules, so they don't really
belong together. This diff moves the code that computes those dependencies
to a new module, get_dependencies.m.

compiler/get_dependencies.m:
compiler/module_imports.m:
    As above. Both modules have significantly better cohesion than
    the old module_imports.m.

compiler/notes/compiler_design.html:
compiler/parse_tree.m:
    Mention the new module.

compiler/hlds_module.m:
compiler/intermod.m:
compiler/module_qual.m:
compiler/modules.m:
    Import get_dependencies as well as, or instead of, module_imports.
2015-07-30 03:34:21 +10:00
Zoltan Somogyi
bed288e06b Group a compilation unit's components together.
compiler/equiv_type.m:
compiler/mercury_compile.m:
compiler/write_module_interface_files.m:
    Instead of passing the various components of a compilation unit
    as separate arguments, pass them as a single compilation unit argument.

compiler/module_qual.m:
    As above, but also eliminate the unnecessary use of generic code,
    in which one the code for one use-case (module qualifying the items
    in parse_tree_int) was shoehorned into using the generalized version
    of the code needed for another use-case (module qualifying an augmented
    compilation unit). The resulting code is shorter, as well as clearer.
2015-07-28 15:23:40 +10:00
Zoltan Somogyi
efb653dac1 Identify the source of imported sections of compilation units.
compiler/status.m:
    We create the augmented compilation unit by adding to the parse tree
    of a source module the interfaces of the other modules it imports
    directly or indirectly. We used to record what section the import
    took place in, but not the identity of the imported module itself.
    This is ok, since the compiler doesn't need that information, and
    a human debugger looking at the augmented compilation unit could
    usually figure it out. However, having to do that "figuring out"
    can be very annoying (I speak from experience). To avoid such
    annoyances in the future, record the identity of the imported module.
    The cost is only a negligible amount of memory and processing.

compiler/equiv_type.m:
compiler/make.module_dep_file.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/write_module_interface_files.m:
    Conform to the above change.
2015-07-24 11:12:13 +10:00