Commit Graph

9 Commits

Author SHA1 Message Date
Zoltan Somogyi
191eb9eb64 Make --generate-dependencies-ints more practical.
scripts/Mmake.rules:
    Add a rule for the pattern target %.depend_ints which invokes mmc
    with --generate-dependencies-ints, just as %.depend invokes mmc
    with --generate-dependencies.

    Document the reason why this addition requires yet more code duplication.

scripts/Mmake.vars.in:
    Add the make variable definitions needed by the new code in Mmake.rules.

compiler/mercury_compile_main.m:
    Make it practical to use --generate-dependencies-ints in a multi-directory
    project like the Mercury implementation, in which some directories
    may use --generate-dependencies-ints as the target of "mmake depend",
    while other directories, which come earlier in the build process,
    still do "mmake depend" using just --generate-dependencies.
    In such cases, mmc --generate-dependencies-ints in the later directory
    may fail to generate .int0, .int or .int2 files simply because
    the .int3 file of a module they import (from an earlier directory
    in which "mmake depend" uses just --generate-dependencies) hasn't been
    made yet. (This is what would happen if someone executed "mmake depend"
    at the top level in a freshly checked out workspace.)

    The practical fix is to simply report this fix using an error message
    that still allows the compiler to exit with an exit status that
    indicates success.

    Most of the rest of this diff is there to make this possible.

compiler/error_spec.m:
    Add a new phase, phase_find_files, that specifically indicates
    that we couldn't read a file because we couldn't find it.
    Give it a string argument naming the file, to allow mercury_compile_main.m
    to replace several error_specs that each report not being able to find
    one file with a single error_spec that reports not being able to find
    many files.

    Add a utility function for use by mercury_compile_main.m to construct
    that error message.

    Add another new phase, phase_make_int, that indicates a problem
    we discovered in the code of a Mercury source file while trying
    to decide what should got into one of the that module's interface files.

compiler/parse_error.m:
    Here also use separate function symbols in the fatal_module_read_error
    type for the situations "couldn't find a file" and "couldn't read a file".

    Update the predicates constructing error_specs to handle this distinction
    (which the callers make using the new function symbol in the above type).

compiler/compile_target_code.m:
compiler/error_util.m:
compiler/grab_modules.m:
compiler/options_file.m:
compiler/parse_module.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.

compiler/options.m:
    Add a way to detect the presence of this diff in an installed compiler.
2023-10-15 13:10:40 +11:00
Zoltan Somogyi
25f8a6cc99 Add new option --generate-dependencies-ints.
This new option extends --generate-dependencies to take advantage of the
opportunity afforded by the fact that "mmc --generate-dependencies prog.m"
reads in every Mercury source file in the current directory that is
part of "prog". It does this by

- generating the .int3 file of all local-directory modules of the program;
- generating the .int0 file for each these modules that has submodules;
- generating the .int and .int2 files of all local-directory modules
  of the program.

Normally, the process of creating .int0, .int and .int3 files would
need to read in .int0 and .int3 files, but in every one of these cases,
we have just written out those files, so simply holding onto their
parse trees, we can skip this step. On my laptop, on a directory
containing library/*.m, mdbcomp/*.m and compiler/*.m, generating
the dependencies and generating all the .int3/.int0/.int/.int2 files
takes just over 25 seconds. Using the new option, the same process
takes less than 10 seconds.

compiler/options.m:
    Add the new option.

compiler/op_mode.m:
    Add a new variant of the existing op_mode for --generate-dependencies,
    which we select in the presence of the new option.

compiler/mercury_compile_main.m:
    Implement the new op_mode.

    Fix an old issue, which is that "mmc --make-private-interface x.m"
    generated a .int0 file for *every* module in x.m, even the modules
    that don't have any submodules.

compiler/deps_map.m:
    The code implementing the new option needs to know which modules
    of the program are in the current directory. The deps_map structure
    built by the code shared with the implementation of --generate-dependencies
    has not needed that info until now, so add a new field to the deps
    structure of each module to provide this info.

compiler/generate_dep_d_files.m:
    Return the deps_map created by the code that implements both
    --generate-dependencies and the new option to mercury_compile_main.m.

compiler/write_module_interface_files.m:
    Add a flag to the predicates that first construct the parse trees of,
    and then write out, .int3/.int0/.int/.int2 files, that
    mercury_compile_main.m can use to tell them to record the parse trees
    in the have read module maps.

    Add new variants of two of those predicates that take some of their
    arguments from burdened_module structures, since that is the form
    in which mercury_compile_main.m has that info.

compiler/module_baggage.m:
    The predicates in write_module_interface_files.m that generate
    .int0/.int/.int2 files take an argument that should be the timestamp
    of the source file they are being derived from, if that timestamp
    is needed for smart recompilation. Until now, we only ever invoked
    those predicates when we have just read in the source file,
    and this timestamp was readily available. The code implementing
    the new option needs to store this info for a short time, and
    the module baggage is the obvious place to store it, so add this field
    to the baggage.

compiler/error_spec.m:
    An invocation of the compiler with new option may report errors that
    prevent the construction of interface files for several modules.
    The new code in mercury_compile.m prints the error_specs that have
    contexts in the order of those contexts, but we want to print
    the messages without contexts (which in this case report that
    certain files could not be written or copied) to have a useful
    order too. Make this possible by allowing the invisible pieces
    we use for ordering to specify that order via a string (in this case,
    the name of the file that e.g. could not be written), rather than
    the only previous option, an integer.

compiler/grab_modules.m:
compiler/make.get_module_dep_info.m:
compiler/make.module_dep_file.m:
    Fill in the new field in the module baggage.

compiler/check_module_interface.m:
compiler/handle_options.m:
compiler/make_hlds_error.m:
compiler/parse_module.m:
compiler/prog_foreign_enum.m:
compiler/typecheck_error_util.m:
compiler/typecheck_msgs.m:
compiler/write_deps_file.m:
compiler/write_error_spec.m:
    Conform to the changes above.
2023-10-12 06:50:07 +11:00
Zoltan Somogyi
f508f24b79 Extend "did you mean" suggestions beyond preds.
compiler/typecheck_error_undef.m:
    Suggest possible "did you mean" names when reporting references
    to undefined functions, not just undefined predicates.

    Generalize the infrastructure used for predicate name suggestions
    to work for function name suggestions as well.

    Delete the code moved to error_spec.m.

compiler/module_qual.qual_errors.m:
    When reporting an undefined entity name that has way to become defined
    without changing its name, suggest possible names.

compiler/error_spec.m:
    Move the code for constructing "did you mean" suggestions here from
    typecheck_error_undef.m, to make it accessible from
    module_qual.qual_errors.m as well.

compiler/hlds_cons.m:
    Add a way to retrieve the names of all the function symbols,
    for use by the new code in typecheck_error_undef.m.

compiler/module_qual.id_set.m:
    Add a way to retrieve the names of all the ids in an id_set,
    for use by the new code in module_qual.qual_errors.m.

    Expand a old comment.

tests/invalid/bug113.err_exp:
tests/invalid/multiply_star.err_exp:
tests/invalid/multiply_star.m:
tests/invalid_nodepend/kind.err_exp:
tests/invalid_nodepend/reserved_type_name.err_exp:
    Expect the "did you mean" messages we now generate.
2023-09-26 18:51:18 +10:00
Zoltan Somogyi
bb5b24173c Add an explicit stream to the print_anything method.
compiler/error_spec.m:
    As above.

compiler/mode_errors.m:
    Get the stream from this extra arg.

compiler/write_error_spec.m:
    Supply the stream argument.
2023-09-13 10:19:52 +10:00
Zoltan Somogyi
51280ed660 Simplify more calls to handle_given_options.
compiler/mercury_compile_main.m:
    The handle_given_options predicate, besides computing the direct effect
    of a given list of command line arguments on the option table, also

    - looks for and reports inconsistencies between option values,

    - applies implications between options, and

    - constructs the global structure.

    The code in the initial part of mercury_compile_main.m has long had
    calls to handle_given_options that did not really need any of this work
    to be done. The calls were nevertheless there because the later code,
    even though it needed unly the updated option table, could only
    *use* that updated option table if it was part of a globals structure.

    This diff makes a start on fixing that. It replaces two calls
    to handle_given_options with calls to getopt.process_options_userdata_io,
    which just returns the updated option table. It updates the code following
    those two calls to use the updated option table directly, NOT through
    a globals structure. The rest of this diff is there to make this possible.

compiler/check_libgrades.m:
    Make maybe_detect_stdlib_grades take an option_table, not a globals
    structure.

compiler/write_error_spec.m:
    Provide a version of write_error_specs that takes an option_table,
    not a globals structure.

    The changes in the following modules are there to implement this change.

compiler/compiler_util.m:
    Provide a version of record_warning that takes an option_table,
    not a globals structure.

compiler/error_sort.m:
    Provide a version of sort_error_specs that takes an option_table,
    not a globals structure.

compiler/error_spec.m:
    Provide a version of extract_spec_msgs that takes an option_table,
    not a globals structure.

compiler/error_util.m:
    Do the same for several functions dealing with severities.
2023-07-12 03:02:59 +02:00
Zoltan Somogyi
cf66008788 Stop using exceptions in the analysis package.
compiler/analysis.m:
compiler/analysis.file.m:
    Instead of throwing an exception when we find an unexpected version
    number or an unrecognized item in a file, construct an error_spec
    describing the problem, add it to the list, and continue processing,
    if this is possible.

    In some places, pass around the information needed for the construction
    of meaningful error messages.

    Note a limitation of the new approach to error handling (that it inherits
    from the old approach).

    Instead of reading in each item in analysis request/result files
    separately, read in their whole files all at once, and just parse it
    item by item.

    Stop marking module_cmds as an unwanted dependency; it defines
    undate_interface_return_changed, which is required for this module's job.

    Give some predicates more meaningful names.

compiler/error_spec.m:
    Fix some documentation rot.

compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
    Act on the error_specs that the analysis package can now return.
2023-04-09 13:41:06 +10:00
Zoltan Somogyi
a4b04b62e1 Use error_specs when checking trans_opt_deps_specs.
compiler/generate_dep_d_files.m:
    When the new code to handle the new --trans-opt-deps-spec option
    found an error, it printed out an error message and then stopped.
    Replace this with code that

    - continues processing after each error, to allow more than one error
      to be reported by a single compiler invocation, and
    - does not any print error messages, but instead returns
      an error_spec for each error.

    In addition, add code to look for and report

    - any references in the trans_opt_deps_spec to module names
      that do not occur in the deps graph that the trans_opt_deps_spec
      is intended to apply to; and
    - any duplicate entries in module name lists.

    To make the above possible, modify the representation of
    trans_opt_deps_specs to include information that is needed
    only for the generation of meaningful error messages.

    Note some potential problems with the code that outputs the deps graph
    as a .dot file.

compiler/error_spec.m:
    Add a mechanism to gather all the contexts in error_specs, for use
    by new code in generate_dep_d_files.

compiler/mercury_compile_main.m:
    Write out the error_specs (if any) returned by generate_dep_d_files.m.
2023-01-13 02:10:43 +11:00
Zoltan Somogyi
3fb55722be Print structured terms on one line if they fit.
The compiler's diagnostic outputs often contain terms, representing
either terms in the program, or other entities such as types or modes.
These can be printed either as

    f(a, b)

or as

    f(
        a,
        b
    )

We usually want the former if the term fits on one line, but the latter
if it is too big to fit on one line. The problem is that the code
generating the diagnostic often does not know what fits on one line.

compiler/error_spec.m:
    This diff adds two new format pieces that respectively stand for
    each half of a matched pair of left and right parentheses.
    The idea is that these can be printed

    - either with a newline, and an indent increment, after the left paren,
      and an indent decrement, and a newline, before the right paren,
      and with all newlines being honored between them,
    - or with no newline after the left paren or before the right paren,
      and all newlines between them being replaced by spaces.

compiler/write_error_spec.m:
    Implement the new format pieces, using the one-line format above
    if the term fits in the space available, or the multi-line format
    if it does not.

compiler/error_type_util.m:
    Use the new mechanism to represent the structure of types.

    Delete an old piece of code that had the same objective,
    but was much cruder and less effective.

tests/invalid/actual_expected.err_exp:
tests/invalid/ext_type_bug.err_exp:
tests/invalid/fbnf.err_exp:
tests/invalid/ho_type_arity_bug.err_exp:
tests/invalid/overloading.err_exp:
tests/invalid/type_diff.err_exp:
    Expect more compact representations of the structure of types.

tests/invalid/type_error_ambiguous.err_exp:
    Expect a different ordering of the same information.
    The difference is due to the changed internal representation
    (in terms of format_pieces) of a type.
2022-10-14 19:13:38 +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