Commit Graph

255 Commits

Author SHA1 Message Date
Zoltan Somogyi
da3e2e80d3 Make invoked_by_mmc_make part of the op_mode.
compiler/op_mode.m:
    Add a field that specifies whether the compiler was invoked by
    "mmc --make" to the opm_top_args top-level op_mode. This is the
    class of op_modes for which we need that info.

    Fill in this new field from the value of the --invoked-by-mmc-make
    option.

compiler/options.m:
    Add an "only_opmode_" prefix to the internal name of the
    --invoked-by-mmc-make option. Move this option next to the --make option.

    Improve the wording of some options' usage messages.

doc/user_guide.texi:
    Make the same changes in wording here as well.

compiler/add_pragma.m:
compiler/add_type.m:
compiler/exception_analysis.m:
compiler/handle_options.m:
compiler/headvar_names.m:
compiler/hlds_module.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_make_hlds.m:
compiler/mode_errors.m:
compiler/op_mode.m:
compiler/options.m:
compiler/post_term_analysis.m:
compiler/post_typecheck.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.versions.m:
compiler/structure_sharing.analysis.m:
compiler/tabling_analysis.m:
compiler/term_util.m:
compiler/trailing_analysis.m:
compiler/unused_args.m:
    Conform to the changes above, either by finding out whether
    the compiler was invoked by mmc --make using the op_mode instead
    of the option, or by ignoring that info where not needed.
2023-03-11 16:55:06 +08:00
Zoltan Somogyi
a32d6a16f4 Add the format_call pragma to the language.
doc/reference_manual.texi:
NEWS:
    Document and announce the new pragma.

compiler/prog_data_pragma.m:
compiler/prog_item.m:
    Provide a representation for the new pragma. The part that ends up
    being referred to from the HLDS goes into prog_data_pragma.m,
    the part that is not needed once the HLDS has been constructed
    goes into prog_item.m.

compiler/hlds_pred.m:
    Add a slot to pred_infos for info from the new pragma.

    Fix a bug in the comment on marker_has_format_call.

compiler/add_pragma.m:
    Add the information in these pragmas to the HLDS.

compiler/check_pragma_format_call.m:
    A new module to check the validity of format_call pragmas.
    These checks test whether the arguments named in such pragmas
    have the expected types and modes, which means that
    the check must be done after both type and mode checking.

compiler/check_hlds.m:
compiler/notes/compiler_design.html:
    Add and document the new module.

compiler/hlds_module.m:
    Add a field to the module_info that records the set of pred_ids
    that have format_call pragmas.

compiler/mercury_compile_front_end.m:
    Invoke the check_pragma_format_call pass *provided* that
    the new field in the module_info says it has any pragmas to check.

compiler/parse_pragma.m:
    Add code to parse the new pragma.

compiler/format_call.m:
    Check calls to predicates and functions with the new pragma
    the same way as we check calls to string.format, io.format,
    and stream.string_writer.format.

    This required separating the code that checked calls to such predicates
    from the code that optimized calls to such predicates, since

    - a predicate or function with a format_call pragma that specifies
      more than one argument pair has to have its correctness checked
      for each pair, and

    - a predicate or function with a format_call pragma does not actually
      do any formatting, so that formatting cannot be optimized.

    Fix an old bug, where we included the function result in the function's
    reported arity, which meant that an error message could mention a call
    to a nonexistent function. As part of that fix, the error message
    now specifies whether it is complaining about a call to a predicate
    or a function.

    Change the exported interface of this module a bit
    in order to allow the factoring out of repeated code.

compiler/parse_string_format.m:
    Separate the parsing of format strings from their optimization,
    again because calls to predicates and functions with format_call
    pragmas need to be checked but cannot be optimized.

compiler/polymorphism.m:
    Record the effect on argument numbers of any type_info and/or
    typeclass_info arguments added by this pass.

compiler/convert_parse_tree.m:
compiler/det_analysis.m:
compiler/direct_arg_in_out.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/hlds_out_pred.m:
compiler/item_util.m:
compiler/module_qual.qualify_items.m:
compiler/parse_tree_out_pragma.m:
compiler/prog_item_stats.m:
compiler/recompilation.version.m:
compiler/simplify_proc.m:
    Conform to the changes above.

tests/invalid/bad_format_call.{m,err_exp}:
    A new test case to see whether check_pragma_format_call.m detects
    and reports invalid format_call pragmas as expected.

tests/warnings/format_call_warning.{m,exp}:
tests/warnings/format_call_warning_helper.m:
    A new test case to see whether we generate the expected set of error
    messages for incorrect calls to a predicate with a format_call pragma.

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

tests/invalid/string_format_bad.err_exp:
tests/invalid/string_format_unknown.err_exp:
tests/warnings/disabled_warning.exp:
    Expect the predicate vs function distinction to the printed in
    error messages about bad calls to formatting predicates and functions.
2022-09-24 08:42:36 +10:00
Zoltan Somogyi
af196031ea Move pred_origin towards a structured pred_name.
compiler/hlds_pred.m:
    Add a long comment about using pred_origin as a structured pred name.

    Delete the origin_created pred_origin with origin_deforestation,
    which was one of two ways that the compiler could create new predicates
    that weren't derived from one existing predicate, procedure, or other
    single Mercury construct. (Deforestation picks a conjunction of two
    or more goals, and created a new predicate out of *them*.)
    Replace the other, created_by_io_tabling, with a pred_transformation,
    since in that case, the new predicate *is* derived from a single
    existing predicate.

    Add a mechanism for recording the predicates created by the distance
    granularity transformation, which previously was recorded in the predicate
    name, but not in the pred_origin.

    Deleted the dnf predicate transform, since it hasn't been used
    since the Aditi backend was deleted in 2006.

    Include the pred_or_func distinction, and the original user arity,
    in the pred_origin of user defined predicates and functions.

    Include in most other pred transformations the parameters that are
    now recorded in the corresponding transform_name used in pred_name.m,
    with the exception of the pred_or_func distinction, since it is now
    available by following the chain of transforms to the base pred_origin,
    which should include that info.

    Use a type_ctor, not its components, in a pred origin.

    Shorten the too-long names of some function symbols.

compiler/distance_granularity.m:
    Record the transform done by this module.

    Use state variables where appropriate.

    Use more consistent variable names.

    Eliminate excessive indentation in the example transformation
    in the module introduction comment.

compiler/loop_inv.m:
    Fix a bug. The sequence number field of the transform_name
    was being filled with something other than a sequence number,
    which could be the same for two transformations. (Or at least,
    I have seen no convincing argument for why they couldn't be.
    If such an argument existed, the sequence number field would
    not be needed, so the old code would still have been wrong,
    just for a different reason :-)

    Rename a predicate to avoid ambiguity.

compiler/hlds_module.m:
    Add the per-context counter needed by the new code in loop_inv.m.

compiler/pd_info.m:
    The predicate that defines a new predicate always specifies
    the transform_name as tn_deforestation, so don't leave it up
    to the caller to specify the pred_origin of the new predicate;
    instead, construct it here as a deforestation transform of the
    base predicate. That is the origin argument that our one caller
    always specified anyway.

compiler/purity.m:
    Use a full switch over pred_origins, not a partial one,
    to make a decision.

compiler/accumulator.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/deforest.m:
compiler/dep_par_conj.m:
compiler/higher_order.m:
compiler/hlds_defns.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/inlining.m:
compiler/layout_out.m:
compiler/lco.m:
compiler/mode_errors.m:
compiler/par_loop_control.m:
compiler/polymorphism.m:
compiler/prog_item.m:
compiler/ssdebug.m:
compiler/table_gen.m:
compiler/trace_params.m:
compiler/tupling.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/xml_documentation.m:
    Conform to the changes above.
2022-07-20 01:05:34 +10:00
Zoltan Somogyi
cb1da20600 Stop ancestor imports "shadowing" unused local imports.
compiler/make_hlds_passes.m:
    We used to add all modules imported by an ancestor of the current module
    to the set of used modules. Once upon a time, this was meant to stop
    the compiler generating misleading warnings about imports being unused
    when the import wasn't even done by the current module. However, since
    we introduced structured representations of import- and use_module
    declarations and taught unused_imports.m to use them, that has not been
    an issue. However, a bad side-effect remained, which was that if
    a module A imported a module B but did not use it, or it imported
    module B in its interface but did not use in its interface, then
    any warning we could generate about that import being unused was
    suppressed by any import of module B in any of module A's ancestors.
    (The "shadowing" mentioned above.)

    Fix the problem by adding modules imported by ancestors of the
    current module NOT to the set of used modules, but to a new field
    in the module_info.

compiler/hlds_module.m:
    Add this new field. As it happens, it is not needed right now,
    but it may be needed later.

    Update some documentation.

    Note an only-tangentially-related problem.

compiler/unused_imports.m:
    Fix a bug that was hiding behind the shadowing, which was that whether
    the text of the warning message we generated for an unused local import-
    or use_module declaration could be affected by the presence of an
    import- or use_module declaration in an ancestor module.

    Improve debugging infrastructure.

    Make a predicate name more descriptive.

NEWS:
    Announce the bugfix.

compiler/add_pragma_tabling.m:
compiler/add_solver.m:
compiler/add_type.m:
compiler/parse_string_format.m:
compiler/recompilation.usage.m:
compiler/recompilation.used_file.m:
library/io.call_system.m:
library/io.text_read.m:
library/random.sfc32.m:
library/random.sfc64.m:
library/random.system_rng.m:
library/string.parse_runtime.m:
library/string.parse_util.m:
library/string.to_string.m:
library/thread.closeable_channel.m:
mdbcomp/feedback.automatic_parallelism.m:
    Delete imports that the fixed compiler now generates unused import
    warnings for.
2022-03-30 13:06:37 +11:00
Zoltan Somogyi
47884b0506 Clarity some code for computing used modules.
compiler/hlds_module.m:
    Document the semantics of the used_module field, and describe a possible
    bug.

    Give a predicate for recording modules as used a more descriptive name.

compiler/make_hlds_passes.m:
    Conform to the change in hlds_module, and factor out both
    common code and common comments.

compiler/prog_data_used_modules.m:
    Move an invariant test on visibility out of a loop.
2022-03-30 02:18:53 +11:00
Zoltan Somogyi
f80261cd00 Put the include_module_map into the module_info.
compiler/hlds_module.m:
    Add this slot in the module_info.

    Get the caller of module_info_init specify the value of this new field,
    as well as another field whose value is known at module_info_init time
    (see below).

compiler/make_hlds_separate_items.m:
    Return the include_module_map from the parse tree of the augmented module.

compiler/make_hlds_passes.m:
    Pass the include_module_map to the predicate that initializes
    the module_info. Move the call to that predicate so that has
    the same position in the text as in the dataflow order.
2022-03-19 16:19:29 +11:00
Zoltan Somogyi
e657a091e4 Encode the arity kind in the type in pred lookups.
compiler/pred_table.m:
    Some predicates in this module have traditionally taken an arity argument
    that *included* function result arguments, while others took an arity
    arguments that *excluded* function result arguments. While the difference
    was documented, it was not enforced in the types. Change this by
    switching the two kinds of arities to pred_form_arities and user_arities
    respectively.

    Change the internal data structures to specify in the types
    that they operate on user_arities.

    Change the operation of lookup_builtin_pred_proc_id as part of the
    change to goal_util.m (described below).

compiler/goal_util.m:
    When looking up the pred_info of a builtin, callers used to pass to the
    predicates that did that (generate_simple_call and generate_foreign_proc)
    a list of the arguments of the call without specifying which arguments
    were type_info/typeclass_info arguments added by polymorphism.
    This meant that the length of the argument list was *not* necessarily
    the called predicate or function's pred form arity, but could exceed it
    by the number of arguments added by polymorphism. The only reason this
    worked was because the lookup_builtin_pred_proc_id procedure they used
    to look up the named predicate in the pred table compensated for it

    - by doing a lookup on the original arity plus one, if the lookup on the
      original arity failed, and

    - in all the calls to generate_simple_call and generate_foreign_proc,
      the number of arguments added by polymorphism was either zero or one.

    Nevertheless, the system was fragile. It could have broken either

    - because when looking up the arity that included a type_info argument,
      (e.g. one typeinfo and two original args) the lookup could have found
      a false match (a predicate with the same name with three original args),

    - or because a new call to a new builtin could need to specify two or more
      arguments added by polymorphism.

    Fix this issue by

    - requiring calls to generate_simple_call and generate_foreign_proc
      to pass the arguments added by polymorphism separately, so the number
      of the original arguments specifies the predicate's pred_form_arity, and

    - deleting the code in lookup_builtin_pred_proc_id that tried to
      compensate for the presence of an "unannounced" typeinfo argument.

compiler/analysis.m:
    Change the type of a slot in a structure from arity to pred_form_arity,
    since that seems to have been how that slot was used.

compiler/recompilation.check.m:
compiler/recompilation.m:
compiler/recompilation.usage.m:
    Conform to the changes above, but only in a minimal fashion,
    because I don't *know* whether the values of type 'arity' passed around
    in the recompilation modules represent user arities or pred form arities.
    Record my guesses, but also record the fact that they are *only* guesses.
    Mark suspect code with "XXX ARITY BUG".

compiler/add_heap_ops.m:
compiler/add_trail_ops.m:
compiler/stm_expand.m:
compiler/table_gen.m:
    Conform to the changes above.

    Rationalize the argument order of the internal module-specific predicates
    they use to generate calls to builtins.

compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/analysis.file.m:
compiler/check_typeclass.m:
compiler/complexity.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/dep_par_conj.m:
compiler/direct_arg_in_out.m:
compiler/distance_granularity.m:
compiler/format_call.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/higher_order.m:
compiler/hlds_module.m:
compiler/intermod.m:
compiler/lco.m:
compiler/make_hlds_passes.m:
compiler/mmc_analysis.m:
compiler/modecheck_goal.m:
compiler/par_loop_control.m:
compiler/polymorphism_type_class_info.m:
compiler/polymorphism_type_info.m:
compiler/pred_table.m:
compiler/purity.m:
compiler/rbmm.region_transformation.m:
compiler/resolve_unify_functor.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_scope.m:
compiler/simplify_goal_unify.m:
compiler/size_prof.m:
compiler/special_pred.m:
compiler/ssdebug.m:
compiler/try_expand.m:
compiler/typecheck.m:
compiler/unify_proc.m:
    Conform to the changes above.
2022-02-22 23:59:20 +11:00
Zoltan Somogyi
068fc20006 Improve error management in convert_parse_tree.m.
compiler/hlds_module.m:
compiler/prog_item.m:
    Record the identity of predicates and functions that have misplaced
    attempts at definition in the interface section using the
    pred_pf_name_arity type instead of the pf_sym_name_arity type.
    They both specify an arity, but only in pred_pf_name_arity is it clear
    *which kind* of arity this is.

compiler/convert_parse_tree.m:
    Record external declarations and foreign_procs in the interface
    as misplaced attempts at predicate or function definition using
    pred_pf_name_arity, so that the code obviously has no arity bugs,
    whereas the old code merely had no obvious bugs. (It did actually work.)

    Record fact_table pragmas in the interface as similar misplaced attempts
    as predicate or function definition, *if* the pragma contains
    a pred_or_func indication.

    Factor out some common code.

compiler/hlds_pred.m:
    Add predicates to return a pred_info's arity as pred_form_arity
    and as user_arity.

compiler/make_hlds_separate_items.m:
compiler/typecheck_errors.m:
    Conform to the changes above.

tests/invalid_nodepend/external_in_interface.{m,err_exp}:
tests/invalid_nodepend/foreign_proc_in_interface.{m,err_exp}:
tests/invalid_nodepend/fact_table_in_interface.{m,err_exp}:
    Three new test cases to test the

tests/invalid_nodepend/Mmakefile:
    Enable the new tests.

tests/invalid/external2.m:
    Fix typo in comment.
2022-02-04 03:14:36 +11:00
Zoltan Somogyi
5cada10369 Rename pred_table to pred_id_table.
compiler/pred_table.m:
    As above. This addresses half of an old XXX, which is that the two types
    defined in this module, predicate_table and pred_table (as it was then)
    should have names that (a) say what they do, and (b) are distinct.
    Addressing the other half requires a more descriptive but not-too-long
    name to replace "predicate_table".

    Rename the predicates that operate on the type to follow the name change.

    Add a distinguishing prefix to the names of the fields of the
    predicate_table type.

compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_special_pred.m:
compiler/arg_info.m:
compiler/bytecode_gen.m:
compiler/clause_to_proc.m:
compiler/closure_gen.m:
compiler/cse_detection.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/default_func_mode.m:
compiler/det_analysis.m:
compiler/det_util.m:
compiler/direct_arg_in_out.m:
compiler/distance_granularity.m:
compiler/export.m:
compiler/float_regs.m:
compiler/goal_mode.m:
compiler/granularity.m:
compiler/hlds_defns.m:
compiler/hlds_error_util.m:
compiler/hlds_module.m:
compiler/hlds_out_goal.m:
compiler/hlds_out_module.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.m:
compiler/hlds_statistics.m:
compiler/implementation_defined_literals.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/lambda.m:
compiler/lco.m:
compiler/make_hlds_passes.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_llds_back_end.m:
compiler/ml_proc_gen.m:
compiler/mode_info.m:
compiler/modecheck_call.m:
compiler/modes.m:
compiler/oisu_check.m:
compiler/old_type_constraints.m:
compiler/passes_aux.m:
compiler/polymorphism.m:
compiler/polymorphism_post_copy.m:
compiler/post_typecheck.m:
compiler/pre_typecheck.m:
compiler/proc_gen.m:
compiler/proc_requests.m:
compiler/simplify_proc.m:
compiler/stm_expand.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.m:
compiler/structure_sharing.analysis.m:
compiler/switch_detection.m:
compiler/table_gen.m:
compiler/term_constr_build.m:
compiler/term_constr_initial.m:
compiler/term_constr_util.m:
compiler/term_util.m:
compiler/termination.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
    Conform to the change in pred_table.m.

    Refer to values of the renamed type using a consistent naming scheme.

    When the affected code repeats the body of existing helper predicates
    for lookup up a pred_info or proc_info, or updating a proc_info
    inside a pred_info, or updating a pred_info inside a module_info,
    call the helper predicate instead. This makes code shorter and less
    cluttered, and the use of the helper predicates for updates automatically
    ensures that we don't accidentally update a stale version of the relevant
    table. (This has sometimes been a problem in the past.)

    In a few places, carve a new predicate for processing one element
    of a list out of an existing predicate for processing all list elements.
2022-02-03 10:01:21 +11:00
Zoltan Somogyi
243491523d Stop counting errors in module_infos.
Over time, we have almost completely switched over to using error_specs,
using their severity (if not yet printed out) and their effect on the
exit status (if already printed out) to represent the presence of errors,
leaving only a few places that either updated or paid attention to the
num_error field in the module_info. This diff completes that process.

compiler/hlds_module.m:
    Delete the num_errors field in the module_info, and the predicates
    that operate on it.

compiler/hlds_error_util.m:
    Delete module_info arguments whose only purpose was to update the
    now-delete field.

compiler/error_util.m:
    Delete the old write_error_spec predicates that updated a count of warnings
    and a count of errors.

    Rename the write_error_spec_ignore predicates, which ignored those counts,
    by deleting the "_ignore" from their names. This makes them take the
    place of the deleted predicates.

compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/compile_target_code.m:
compiler/cse_detection.m:
compiler/find_module.m:
compiler/generate_dep_d_files.m:
compiler/handle_options.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.top_level.m:
compiler/make.track_flags.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mode_info.m:
compiler/modes.m:
compiler/pd_util.m:
compiler/pred_table.m:
compiler/recompilation.check.m:
compiler/typecheck.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.
2022-01-15 16:33:38 +11:00
Zoltan Somogyi
e2f524d033 Replace some item-block-scanning code.
compiler/module_imports.m:
    There were two data structures, the list of foreign include files
    and the "contains foreign export" flag) that we used to to compute twice:
    once using old code that scanned a list of item blocks, and once using
    more modern data structures. Delete the old-code versions, since
    we haven't had a discrepancy between the two versions for a long time.

    For a third data structure, the set of fims (foreign_import_modules),
    add the new code version, and add code to check for discrepancies.

compiler/item_util.m:
    Delete the old code that used to compute the first two data structures.

compiler/prog_data_foreign.m:
    Add a utility predicate for use by module_imports.m. Give some predicates
    shorter names.

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

compiler/make.dependencies.m:
    Clarify a piece of code.
2021-07-11 20:15:33 +10:00
Zoltan Somogyi
34e7be6404 Don't import an unneeded module in the interface. 2021-05-29 20:36:58 +10:00
Zoltan Somogyi
e10bc34a74 Implement mutables only in prog_mutable.m.
compiler/prog_mutable.m:
    Move code implementing mutables here, mostly from add_mutable_aux_preds.m,
    but some from comp_unit_interface.m. Export only what those two modules
    need.

    Replace the

compiler/add_mutable_aux_preds.m:
compiler/comp_unit_interface.m:
    Delete the code moved to prog_mutable. In add_mutable_aux_preds.m,
    make minor rearrangements to make this possible.

compiler/hlds_module.m:
compiler/prog_foreign.m:
    Move the pred_target_names type, and two predicates that operate
    on it, from hlds_module.m to prog_foreign.m, to make it accessible
    from prog_mutable.m, which is part of the parse_tree package, and thus
    should not import anything from the hlds package.

compiler/prog_item.m:
    Move a (renamed) type here from add_mutable_aux_preds.m, since
    prog_mutable.m now needs access to it as well.

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

compiler/prog_data.m:
    Fix some old comments.
2021-05-27 22:06:33 +10:00
Zoltan Somogyi
e1e2136dbb Centralize HLDS building in make_hlds_passes.m.
compiler/add_mutable_aux_preds.m:
compiler/add_solver.m:
    When invoked on mutables and solver types respectively, these modules
    added did all the additions to the HLDS directly themselves,
    in two phases: first declarations, then definitions.

    Change this so that instead, they simply return the items needed
    to declare and define mutables and solver types to make_hlds_passes.m,
    which will then add them to the HLDS with the other items of the same kind.

compiler/make_hlds_passes.m:
    Add to the HLDS the items returned by add_mutable_aux_preds.m and
    add_solver.m. Doing the adding here makes it much easier to see
    both the full set of items that mutables and solver types, as well as
    the dependencies between them and other kinds of items.

compiler/add_foreign_proc.m:
    Add a utility predicate for use by the code above.

compiler/add_pragma.m:
    Add a utility predicate for use by the code above, replacing another,
    which can now be kept private.

compiler/make_hlds.m:
    Define types that are now needed in more than one of its submodules.

compiler/make_hlds_separate_items.m:
    Delete the type definitions that have been moved to make_hlds.m.

compiler/hlds_module.m:
    Rename pred_c_names as pred_target_names, since they can also refer to
    C# and Java names.

    Change the predicates that add pred_target_names so that they add them
    to just the data structure that contains them, not the whole module_info.
    This makes the code of the callers clearer.

    Fix a bug I introduced when I changed make_hlds_passes.m to add items
    by kind, not by position in an item block. The bug was that the
    reference manual promised that in the event of a code sequence such as

        :- initialise foo/2.
        :- mutable(bar, int, 561, ground, [untrailed]).
        :- initialise baz/2.

    the initialization of bar would happen *between* the calls to
    foo/2 and baz/2, but since make_hlds_passes.m processed all initialise
    declarations together, this could not happen. The fix is to record
    initializations in a map whose key is an item sequence number
    (which cannot be item_no_seq_num), and then take the initialization
    sequence from those keys.

compiler/parse_type_defn.m:
    Include valid seq_nums (the seq_num of the solver type definition)
    in the mutable items returned for solver types, for use in the
    pred_target_names map in hlds_module.m.

compiler/mercury_compile_llds_back_end.m:
compiler/ml_top_gen.m:
    Conform to the change in hlds_module.m.
2021-05-24 22:01:17 +10:00
Zoltan Somogyi
63dabcfcf8 Fix filling in partial terms that use direct_arg tags.
This fix uses the approach discussed on m-dev 2020 nov 16/17 for fixing
github issue #72, whose core problem is a need for information flow
back to a the caller from a callee when the callee fills in the
argument of a function symbol whose representation is a direct_arg tag.
In most cases when the callee fills in the value of an argument,
the caller can see it because the argument is in a word on the heap,
but when the function symbol uses a direct_arg tag, that is not the case.

compiler/direct_arg_in_out.m:
    A new module that implements the transformation proposed on m-dev.
    It creates a fresh clone variable every time an argument of a direct_arg
    tag function symbol is (or may be) updated. This can happen several
    times if a type has more than one function symbol with a direct_arg tag.
    Since the affected variable can be bound to only one function symbol
    at the start, its argument can be filled in only once, but the
    compiler cannot know in advance what function symbol the variable
    contains, and therefore which of the possibly several fill-in sites
    (which fill in the arguments of different function symbols) executed
    in sequence will actually update the variable.

    The transformation ensures that once a variable is cloned, it is
    never referred to again. It also ensures that in a branched control
    structure (if-then-else, disjunction or switch), all branches will use
    the *same* variable to represent the latest version of each cloned
    variable at the end, so that following code has a consistent view
    regardless of through which branch execution has reached it.

    There are three situations that the transformation cannot and does not
    handle.

    1. Situations in which the mode of an argument is either an inst variable,
       or an abstract inst. In either case, the pass cannot know whether
       it should apply its transformation to the argument.

    2. Situations where a procedure that has such an argument is
       exported to C code as a function. In that case, the C signature
       of the function we would generate would be different from what
       the user would normally expect. We could modify the documentation
       of the export pragma, but I don't think there much point due to
       lack of demand. (The problem cannot arise when targeting any language
       other than C, because we use direct_arg tags only with the low level
       data representation, which we only use for C.)

    3. Situations where a procedure that has such an argument is defined
       by foreign_proc. Again, dealing with the problem would require
       nontrivial changes to the documented interface between code in
       foreign_procs and the surrounding Mercury code, and I see no demand
       for code that could benefit from that.

    In these cases, this module generates error messages.

compiler/transform_hlds.m:
    Include the new module in the transform_hlds package.

    Delete unnecessary module qualification on some existing inclusions.
    Put some existing inclusions into a more meaningful order.

compiler/notes/compiler_design.html:
    Document the new pass. Fix some nearby prose.

compiler/lambda.m:
compiler/simplify_proc.m:
    Use a predicate exported by direct_arg_in_out.m to test, for each
    procedure, whether the procedure has any argument positions that are
    subject to the problem that direct_arg_in_out.m addresses.
    simplify_proc.m does this for all procedures it processes;
    lambda.m does this for all the procedures it creates from
    lambda expressions.

    Give a predicate in simplify_proc.m a better name.

    Sort a list of predicate names.

compiler/hlds_module.m:
    Add a field to the module_info that simplify_proc.m and lambda.m
    can use to tell direct_arg_in_out.m what work (if any) it needs to do.

compiler/mercury_compile_middle_passes.m:
    Invoke direct_arg_in_out.m if the new field in the HLDS indicates
    that it has some work to do. (In the vast majority of compiler invocations,
    it won't have any.)

compiler/hlds_pred.m:
    The new code in direct_arg_in_out.m creates a clone of each procedure
    affected by the problem, before deleting the originals (to make sure that
    no references to the unfixed versions of now-fixed procedures remain.)
    Make it possible to create exact clones of both predicates and procedures
    by adding two pairs of predicates, {pred,proc}_prepare_to_clone and
    {pred,proc}_create.

    Add the direct_arg_in_out transformation as a possible source
    of transformed predicates.

library/private_builtin.m:
    Add a new builtin operation, partial_inst_copy, that the new module
    generates calls to.

configure.ac:
    Require the installed compiler to recognize partial_inst_copy
    as a no_type_info builtin.

compiler/builtin_ops.m:
    Recognize the new builtin. (This was committed before the rest; the diff
    to private_builtin.m can be done only once the change to builtin_ops.m
    is part of the installed compiler.)

compiler/options.m:
    Add a way to test whether the builtin_ops.m in the installed compiler
    recognizes the new builtin.

compiler/dead_proc_elim.m:
    Do not delete the new primitive before direct_arg_in_out.m has had
    a chance to generate calls to it.

    Add an XXX.

compiler/error_util.m:
    Recognize the new module as a source of error messages.

compiler/pred_table.m:
    Add a pair of utility predicates to be used when looking up
    builtin predicates, for which the compiler writer knows that
    there should be exactly one match. These are used in direct_arg_in_out.m.

compiler/simplify_goal_call.m:
    Replace some existing code with calls to the new predicates
    in pred_table.m.

compiler/hlds_goal.m:
    Add modes to rename_vars_in_goal_expr that express the fact
    that when an atomic goal_expr has some variables renamed inside it,
    it does not suddenly become some *other* kind of goal_expr.
    New code in direct_arg_in_out.m relies on this.

compiler/hlds_out_goal.m:
    When the HLDS we are dumping out is malformed because it contains
    calls to predicates that have been deleted, the compiler used to abort
    at such calls. (I ran into this while debugging direct_arg_in_out.m.)

    Fix this. When such calls are encountered, we now print out as much
    information we can about the call, and prefix the call with an
    unmistakable prefix to draw attention to the problem.

compiler/inst_util.m:
    Fix a bug that prevented direct_arg_in_out.m from even being invoked
    on some test code for it.

    The bug was in code that we use to unify a headvar's initial inst
    with its final inst. When the initial inst was a non-ground bound_inst
    such as the ones used in tests/hard_coded/gh72.m, and the final inst
    was simply "ground", this code quite properly returned a bound_inst
    (which, unlike ground, can show the exact set of function symbols
    that the headvar could be bound to). The problem was that it
    reused the original bound_inst's test results, including the one
    that said the final inst is NOT ground, which of course is wrong
    for any inst unified with ground. Fix two instances of this bug.

compiler/modes.m:
    Make some of the code I had to traverse to find the bug in inst_util.m
    easier to read and understand.

    Replace some uses of booleans with bespoke enum types.

    Change the argument lists of some predicates to put related arguments
    next to each other.

    Give some variables more descriptive names.

compiler/layout_out.m:
    Conform to the change in hlds_pred.m.

compiler/var_locn.m:
    Fix a code generation bug. When filling-in the value of the argument
    of a function symbol represented by a direct_arg tag, the code we
    generated for it worked only if the direct_arg tag used 0
    as its ptag value. In the test cases we initially used for
    github issue 72, that was the case, but the new tests/hard_coded/gh72.m
    has direct_tag args that use other ptag values as well.

    Document the reason why the updated code works.

compiler/term_constr_initial.m:
    Add the new primitive predicate added to private_builtin.m,
    partial_inst_copy, to a table of builtins that do not take type_infos,
    even though their signatures contain type variables.

    Fix a bunch of old bugs: most other such primitives were not listed
    either.

mdbcomp/program_representation.m:
    Add partial_inst_copy to the master list of builtins that do not take
    type_infos even though their signatures contain type variables. (Done
    by an earlier commit.)

    Document the fact that any updates here require updates to
    term_constr_initial.m.

library/multi_map.m:
    We have long had multi_map.add and multi_map.set as synonyms,
    but we only had multi_map.reverse_set. Add multi_map.reverse_add
    as a synonym for it.

    Define the "set" versions in terms of the "add" versions,
    instead of vice versa.

NEWS:
    Document the new predicates in multi_map.m.

tests/hard_coded/gh72a.m:
    Fix typo.

tests/hard_coded/gh72.{m,exp}:
    A new, much more comprehensive test case than gh72a.m.
    This one tries to tickle github issue 72 in as many forms of code
    as I can think of.

tests/invalid/gh72_errors.{m,err_exp}:
    A test case for testing the generation of error messages for
    two out of the three kinds of situations that direct_arg_in_out.m
    cannot handle. (Proposals for how to test the third category welcome.)

tests/hard_coded/Mmakefile:
tests/invalid/Mmakefile:
    Enable the two new test cases, as well as two old ones, gh72[ab].m,
    that previously we didn't pass.

tests/invalid/Mercury.option:
    Do not compile gh72_error.m with --errorcheck-only, since its errors
    are reported by a pass that --errorcheck-only does not invoke.
2021-01-13 05:35:40 +11:00
Zoltan Somogyi
a19a5f0267 Delete the Erlang backend from the compiler.
compiler/elds.m:
compiler/elds_to_erlang.m:
compiler/erl_backend.m:
compiler/erl_call_gen.m:
compiler/erl_code_gen.m:
compiler/erl_code_util.m:
compiler/erl_rtti.m:
compiler/erl_unify_gen.m:
compiler/erlang_rtti.m:
compiler/mercury_compile_erl_back_end.m:
    Delete these modules, which together constitute the Erlang backend.

compiler/notes/compiler_design.html:
    Delete references to the deleted modules.

compiler/parse_tree_out_type_repn.m:
    Update the format we use to represent the sets of foreign_type and
    foreign_enum declarations for a type as part of its item_type_repn_info,
    now that Erlang is no longer a target language.

compiler/parse_type_repn.m:
    Accept both the updated version of the item_type_repn_info and the
    immediately previous version, since the installed compiler will
    initially generate that previous version. However, stop accepting
    an even older version that we stopped generating several months ago.

compiler/parse_pragma_foreign.m:
    When the compiler finds a reference to Erlang as a foreign language,
    add a message about support for Erlang being discontinued to the error
    message.

    Make the code parsing foreign_decls handle the term containing
    the foreign language the same way as the codes parsing foreign
    codes, procs, types and enums.

    Add a mechanism to help parse_mutable.m to do the same.

compiler/parse_mutable.m:
    When the compiler finds a reference to Erlang as a foreign language,
    print an error message about support for Erlang being discontinued.

compiler/compute_grade.m:
    When the compiler finds a reference to Erlang as a grade component,
    print an informational message about support for Erlang being discontinued.

compiler/pickle.m:
compiler/make.build.m:
    Delete Erlang foreign procs and types.

compiler/add_foreign_enum.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_type.m:
compiler/check_libgrades.m:
compiler/check_parse_tree_type_defns.m:
compiler/code_gen.m:
compiler/compile_target_code.m:
compiler/compute_grade.m:
compiler/const_struct.m:
compiler/convert_parse_tree.m:
compiler/dead_proc_elim.m:
compiler/decide_type_repn.m:
compiler/deps_map.m:
compiler/du_type_layout.m:
compiler/export.m:
compiler/foreign.m:
compiler/globals.m:
compiler/granularity.m:
compiler/handle_options.m:
compiler/hlds_code_util.m:
compiler/hlds_data.m:
compiler/hlds_module.m:
compiler/inlining.m:
compiler/int_emu.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/lco.m:
compiler/llds_out_file.m:
compiler/make.dependencies.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_warn.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/ml_code_util.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_target_util.m:
compiler/ml_top_gen.m:
compiler/mlds.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_export.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_export.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_type.m:
compiler/module_imports.m:
compiler/parse_pragma_foreign.m:
compiler/parse_tree_out.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/prog_data.m:
compiler/prog_data_foreign.m:
compiler/prog_foreign.m:
compiler/prog_item.m:
compiler/simplify_goal_scope.m:
compiler/special_pred.m:
compiler/string_encoding.m:
compiler/top_level.m:
compiler/uint_emu.m:
compiler/write_deps_file.m:
    Remove references to Erlang as a backend or as a target language.

tests/invalid/bad_foreign_code.{m,err_exp}:
tests/invalid/bad_foreign_decl.{m,err_exp}:
tests/invalid/bad_foreign_enum.{m,err_exp}:
tests/invalid/bad_foreign_export.{m,err_exp}:
tests/invalid/bad_foreign_export_enum.{m,err_exp}:
tests/invalid/bad_foreign_import_module.{m,err_exp}:
tests/invalid/bad_foreign_proc.{m,err_exp}:
tests/invalid/bad_foreign_type.{m,err_exp}:
    Add a test for Erlang as an invalid foreign language. Expect both the
    new error message for this new error, and the updated list of now-valid
    foreign languages on all errors.
2020-10-29 13:24:49 +11:00
Zoltan Somogyi
5c679330ff Update a comment. 2020-08-25 12:58:43 +10:00
Zoltan Somogyi
15b01ee444 Clarify the interface of module_info_init. 2020-08-25 12:57:16 +10:00
Zoltan Somogyi
206cc8503b Revisit valid vs all proc_ids in a pred_info.
compiler/hlds_pred.m:
    We have several predicates that retrieve selected subsets of all
    the proc_ids in a pred_info. For those that retrieve the proc_ids
    of only valid procedures, put "valid" into their names.

    Fix a bug in the implementation of pred_info_all_non_imported_proc_ids,
    which, despite its name, used to return the proc_ids of only the
    *valid* non-imported procedures.

    The distinction between all procedures and only valid procedures
    only really matters between mode analysis and the end of the front end.
    A procedure is valid if it has no mode errors, so before mode analysis,
    all procedures are valid by default, and if any procedure has any
    mode errors, the compiler should terminate after the front end is done.

    However, the distinction matters for readability, so this diff changes
    things so that we get all proc_ids in code executed before mode analysis,
    and valid proc_ids after the front end, with calls handled on a case-by-
    case basis in between.

    The distinction also matters in the presence of errors. For example,
    we shouldn't tell users that a predicate has no modes when it has
    modes that all happen to be invalid, and we should dump procedures
    into .hlds_dump files even if they are invalid, since their invalidity
    may be exactly what the user is trying to debug.

compiler/*.m:
    Make the changes described above.

    In some places, fix bad programming style.
2020-07-30 19:46:14 +10:00
Zoltan Somogyi
14dbd4a46b Simplify implicit dependency on builtin.m.
compiler/get_dependencies.m:
    The interface of the predicates that computed implicit dependencies
    used to return
    (a) the set of modules a piece of code needs to ":- import_module", and
    (b) the set of modules a piece of code needs to ":- use_module".
    However, set (a) *always* contained only one module: builtin.m.
    This lead to a lot of unnecessary operations on this "set".
    The problem with those operations was not the performance impact,
    which is negligible, but the fact that they made the code harder
    to understand.

    This diff therefore changes that interface to return only (b),
    and to document what callers should use for (a).

compiler/grab_modules.m:
compiler/hlds_module.m:
compiler/module_imports.m:
    Conform to the change above.
2020-05-28 08:02:11 +10:00
Zoltan Somogyi
c96f19e56f Put type_repn items into a map.
compiler/make_hlds_separate_items.m:
    We used to return the type_repn items we read in from interface files
    as a list. However, this list could have duplicates, because in the
    presence of intermodule optimization, we can read more than one
    interface file for a module, e.g. a .int3 file as an indirect dependency
    and a .int file as an int_for_opt dependency (i.e. an interface file
    that we need to make sense of some things in a .opt file).

    This diff keeps the type_repn items from only one interface file per
    module, the file that contains strictly more type representation
    information.

    Return this information in the form in which we will want to use it,
    a map that enables lookups. Doing it here should be faster than having
    it done elsewhere, since we can exploit the data structure we use
    to reject redundant type_repns from subsumed interface files to
    build the final version of the map directly, without having to go through
    any intermediate versions.

compiler/hlds_module.m:
    Store type_repn information in the HLDS in map form.

compiler/make_hlds_passes.m:
    Record type_repn information in the HLDS in map form.

compiler/du_type_layout.m:
    Delete the code that used to build this map, since that jobs is now done
    in make_hlds_separate_items.m.
2020-05-23 19:51:16 +10:00
Zoltan Somogyi
26b741c828 Fix typo in field name. 2020-05-01 02:20:20 +10:00
Zoltan Somogyi
5c52cf0cde Standardize on "sym_name_arity" ...
... replacing "sym_name_AND_arity".
2020-03-15 19:37:18 +11: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
b4b3ceb487 Don't export a getter predicate unnecessarily. 2019-12-03 20:14:02 +11:00
Zoltan Somogyi
d4a175407e Add all pragmas in one pass.
compiler/hlds_module.m:
    Split the field containing foreign_decls into two: the decls added
    by the user, and the decls added by the compiler. The latter can refer
    to entities defined in the former, but not the reverse.

compiler/erl_code_gen.m:
compiler/export.m:
compiler/mercury_compile_llds_back_end.m:
compiler/ml_top_gen.m:
    Always put the foreign decls generated by the compiler *after* the ones
    written by the user. The other way around could cause the target language
    compiler to see a use of a type name before its definition.

compiler/add_mutable_aux_preds.m:
compiler/add_pragma.m:
    Add both user-provided and compiler-generated foreign decls to the
    relevant field of the HLDS.

compiler/make_hlds_passes.m:
    Document why we don't have to add any pragmas in the modern equivalent
    of the old pass 2 anymore. The separation of user and auxiliary foreign
    decls was the last issue tying us to that old scheme.

compiler/prog_foreign.m:
    Delete two type synonyms that are not really needed.
2019-11-27 00:12:10 +11:00
Zoltan Somogyi
8e62f93c4d Use maps for several kinds of items in interface file parse trees.
Using lists to store type-, inst- and mode definitions, foreign enum
definitions and type representation items does nothing to enforce
uniqueness requirements, such as "every inst constructor should have
at most one one non-abstract definition in the interface of a module".
However, one can encode such requirements using maps.

This diff therefore changes the representation of these kinds of items
inside the interface-kind-specific parse trees of interface files to use
these kinds of maps. It does not take advantage of the possilities
offered by this diff; that is for a later change.

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

    Since after this diff, the info in foreign_enum pragmas will be in a map,
    while the info in other kinds of pragmas will still be in a list, avoid
    the possibility of being able to represent invalid states by giving
    foreign enums their own item kind, separate from that of pragmas.
    Since foreign export enums are handled very similarly to foreign enum
    pragmas in many places, given them their own item kind as well.

    Update the predicates converting generic interface file parse trees
    to interface-kind-specific parse trees, and vice versa, to conform
    to the changes above.

compiler/comp_unit_interface.m:
    Convert lists to maps before putting them into interface-kind-specific
    parse trees where the above change requires it.

compiler/hlds_module.m:
    Delete types that contain almost exactly the same info as the item
    information we now keep for foreign enum and foreign export enum items.

    Include the item status next to foreign enum items, since that is the
    one piece of info the deleted types had that we need.

compiler/parse_pragma.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
    Parse and print out foreign enums and foreign export enums as their
    own item kinds, not as kinds of pragmas.

compiler/add_foreign_enum.m:
compiler/canonicalize_interface.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
compiler/prog_item_stats.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
    Conform to the changes above.
2019-09-12 03:52:10 +10:00
Zoltan Somogyi
b6d4d3f30d Fix more issues reported by --warn-inconsistent-pred-order-clauses. 2019-08-24 07:53:41 +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
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
c1bdd2100b Delete unneeded $module args from aborts. 2019-04-16 04:13:35 +10:00
Zoltan Somogyi
4bcb3fd227 Add XXXs for possible unnecessary duplication of work. 2019-02-02 23:50:00 +11:00
Zoltan Somogyi
5cf4d9608f Make foreign_import_module a separate kind of item.
compiler/prog_item.m:
    Change foreign_import_module from being a kind of pragma item, to being
    an item in its own right. Although we use pragma syntax to represent them,
    they are NOT allowed in source files. (Though we do not yet enforce this.)

compiler/add_pragma.m:
compiler/comp_unit_interface.m:
compiler/equiv_type.m:
compiler/get_dependencies.m
compiler/hlds_module.m::
compiler/intermod.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qualify_items.m:
compiler/modules.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
compiler/prog_item_stats.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/write_module_interface_files.m:
    Conform to the change above by treating the item kind as the pragma kind
    it replaced.

compiler/parse_pragma.m:
    As above, but also improve variable names.

compiler/item_util.m:
    Conform to the change above, but treat the item kind differently from
    the pragma kind it replaced, by not stating that foreign_import_module items
    require the presence of *other* module imports. (They don't.)
2019-01-29 02:58:01 +11:00
Zoltan Somogyi
5eae909f78 Split hlds_cons.m from hlds_data.m.
compiler/hlds_cons.m:
compiler/hlds_data.m:
    Move the parts of hlds_data.m dealing with the cons table
    (representing the function symbols visible in the current module)
    and with the fields within those function symbols to the new module
    hlds_cons.m. This code was a large fraction of hlds_data.m, yet it is
    needed by relatively few modules.

compiler/hlds.m:
compiler/notes/compiler_design.html:
    Add and document the new module.

compiler/*.m:
    Import the new module as well as, or instead of, hlds_data.m.
2018-10-26 00:30:12 +11:00
Zoltan Somogyi
c4dce74bb4 Improve the treatment of promises.
compiler/check_promise.m:
    Fix github issue #50. If a promise is imported from another module,
    do not process it. Processing would require the pred_id/proc_id slots
    in plain_calls to have been filled in by typechecking, but we don't
    invoke the typechecker on imported code.

compiler/assertion.m:
    Improve the documentation of the predicates that test whether
    an assertion falls into a given category of assertion. Provide variants
    of those predicates that work on goals as well as on assert_ids, so later
    we can test whether assertions fall into any of those categories.

    Add an XXX for what I am pretty sure is a bug.

compiler/hlds_module.m:
compiler/make_hlds_passes.m:
compiler/prog_data.m:
compiler/typecheck.m:
    Improve some comments.

tests/valid/github_50.m:
tests/valid/github_50.submodule.m:
    The two-module test case from github, changed to reflect our coding
    standards.

tests/valid/Mmakefile:
    Test that compiling the new test case does not cause a compiler abort.
2018-10-01 06:54:00 +10:00
Zoltan Somogyi
f4bd666ec6 Simplify the handling of foreign_export_enums.
compiler/hlds_module.m:
    Change the representation of the mapping from Mercury constants
    to their exported foreign names from being a sym_name->string map
    to being a plain string->string map. Several parts of the compiler
    already required the sym_name key to be unqualified, which meant
    that its information content was just the constant's name anyway.
    This change enforces that invariant by encoding it in the data type.

    Document the fields of exported_enum_info. Put those fields into
    an order that makes this documentation flow logically.

compiler/add_foreign_enum.m:
    Rationalize the way foreign_export_enums (FEEs) are processed and checked.
    Check each entry in the override map just once, when it is first processed,
    and string away its module qualification then (after checking it).
    (Leaving the qualification check until later was probably the reason
    for the choice of a sym_name->string map in the old version.)

    Check whether the override map deviates from a bijection by keeping track
    of which Mercury constant names and which foreign names we have seen so
    far. This allows the error messages about "not a bijection" to say *why*
    the mapping is not a bijection. It also fixes an old bug that generated
    a "not a bijection" error for override maps that *were* bijections,
    but were bijections that covered only *some* of the enum type's constants.

    In error messages that include lists of constants or foreign names,
    consistently precede those lists with nl_indent_delta(2).

    Use a more consistent variable naming scheme.

compiler/export.m:
compiler/ml_type_gen.m:
    Conform to the changes in hlds_module.m.

tests/invalid/ee_invalid.err_exp:
tests/invalid/exported_foreign_enum.err_exp:
    Include the updated error messages in these expected outputs.

    Don't expect *any* error message for the FEE on line 75 of ee_invalid.m,
    which has a bijective (though incomplete) override map.
2018-02-24 13:50:52 +11:00
Zoltan Somogyi
dfe108251a Simplify the representation of foreign_export_enums.
compiler/hlds_module.m:
    The backends need to know how each constant in an enum type
    is represented if that type has a foreign_export_enum pragma.
    Transmit that information to them using the ctor_repns of the constants,
    so that they don't have to recreate it from the name of the constant
    and the cons_id_to_tag_map.

compiler/ml_type_gen.m:
    Conform to the change in hlds_module.m.

    Factor out a switch converting enums' tags to rvals that was duplicated
    in two places.

compiler/export.m:
    Conform to the change in hlds_module.m.

    Include the foreign name of an enum constant with its representation;
    this simplifies the code.

compiler/add_foreign_enum.m:
    Conform to the change in hlds_module.m.

compiler/mlds.m:
    Document the reason why the MLDS representation of exported enums
    needs to know the type constructor.
2018-02-21 20:15:47 +11:00
Zoltan Somogyi
70579e1423 Decide each type's representation just once.
compiler/du_type_layout.m:
    Rewrite (most of) this module.

    The old algorithm was designed to preserve the approach of legacy code,
    which could "decide" the representation of a type several times, each
    decision overruling the previous decisions. (The first decision was for
    an unoptimized representation, the second tried to pack function symbols'
    arguments, and the third tried to apply the direct_arg optimization.)
    This made the code significantly harder to understand, and therefore
    to modify.

    The rewrite replaces this algorithm with a totally new one. It works
    in two passes, with the first pass fully deciding the representation
    of simple types (dummy types, enums, and notag types) and gathering
    some information, and the second pass fully deciding the representation
    of all other types (using the information gathered in pass 1).
    With this design, no decision is ever overruled, which makes
    modifications *much* easier.

    This initial version of the new algorithm produces the exact same
    type table as the old algorithm (verified by an automatic comparison)
    in the hlc.gc, asm_fast.gc, asm_fast.gc.debug, csharp and java grades.
    It contains some places where it intentionally does not take advantage
    of optimization opportunities revealed by the new algorithm structure
    to preserve this fact. Those opportunities will be seized by later
    changes.

compiler/hlds_data.m:
    We already had a predicate to convert the type table to an assoc_list
    of type_ctors and type definitions. Add a predicate to convert in
    the reverse direction as well, from assoc list to type table.
    This is used by new code in du_type_layout.m.

compiler/hlds_module.m:
    Give a name to a type used frequently in du_type_layout.m.

compiler/du_type_layout_old.m:
    A copy of the old version of du_type_layout.m, which compares
    the output of its new algorithm with the output of the old.
    Intended to be used only for a few days of checks.

compiler/hlds.m:
    Add du_type_layout_old.m.
2018-02-16 15:04:30 +11:00
Zoltan Somogyi
28e9a29fc2 Carve hlds_inst_mode.m out of hlds_data.m.
compiler/hlds_class.m:
    New module containing the parts of hlds_data.m that deal with
    insts and modes.

compiler/hlds_data.m:
    Delete the moved code.

compiler/hlds.m:
    Include the new module.

compiler/notes/compiler_design.html:
    Document the new module.

compiler/*.m:
    Conform to the changes above.
2018-02-06 06:20:52 +11:00
Zoltan Somogyi
1693c784fe Carve hlds_class.m out of hlds_data.m.
compiler/hlds_class.m:
    New module containing the parts of hlds_data.m that deal with
    type classes and type class constraints.

compiler/hlds_data.m:
    Delete the moved code.

compiler/hlds.m:
    Include the new module.

compiler/notes/compiler_design.html:
    Document the new module.

compiler/add_class.m:
compiler/base_typeclass_info.m:
compiler/check_typeclass.m:
compiler/dead_proc_elim.m:
compiler/float_regs.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_defns.m:
compiler/hlds_module.m:
compiler/hlds_out_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.m:
compiler/intermod.m:
compiler/polymorphism.m:
compiler/post_typecheck.m:
compiler/recompilation.usage.m:
compiler/resolve_unify_functor.m:
compiler/type_assign.m:
compiler/type_class_info.m:
compiler/type_constraints.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/typeclasses.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
    Conform to the changes above.
2018-02-06 02:00:08 +11:00
Zoltan Somogyi
f0db887cd3 Move promises from hlds_data.m to the new hlds_promise.m.
compiler/hlds_promise.m:
    New module carved out of hlds_data.m.

compiler/hlds_data.m:
    Delete the moved code.

compiler/hlds.m:
compiler/notes/compiler_design.html:
    Include the new module.

compiler/accumulator.m:
compiler/assertion.m:
compiler/check_promise.m:
compiler/hlds_module.m:
compiler/hlds_pred.m:
compiler/intermod.m:
    Conform to the change above.
2018-02-05 23:39:52 +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
b0eac2e9a7 Carve proc_requests.m out of unify_proc.m.
compiler/unify_proc.m:
compiler/proc_requests.m:
    The old unify_proc.m contained two kinds of predicates: those that
    generated the source code for unify, index and compare predicates,
    and those that managed the queue of procedure requests. The only link
    between the two is that the latter calls one of the former.

    This diff moves the predicates that deal with the queue of procedure
    requests into a new module, proc_requests.m. This increases the cohesion
    of both new modules.

compiler/check_hlds.m:
compiler/notes/compiler_design.html:
    Include the new module in the check_hlds package.

compiler/hlds_module.m:
compiler/modecheck_call.m:
compiler/modecheck_unify.m:
compiler/modes.m:
compiler/simplify_goal_unify.m:
    Import proc_requests.m instead of unify_proc.m.
2017-06-29 12:31:57 +02:00
Zoltan Somogyi
61d0c67243 Improve diagnostics for foreign_{export_,}enum pragmas.
We can now generate error messages for types that have both foreign_enum
and reserve_tag pragmas, which we couldn't before. (In some cases,
we used to get a compiler abort.)

compiler/add_foreign_enum.m:
    Don't stop after finding the first problem with a foreign_export_enum
    or foreign_enum pragma; if a pragma has more than one problem,
    generate reports for them all.

    When reporting that the type named in a foreign_export_enum or
    foreign_enum is not an enum type, have the error message say *why*.

    Fill in the two new fields in exported_enum_infos (see below).

compiler/make_hlds_passes.m:
    Add reserve_tag pragmas to the HLDS before adding foreign_export_enum
    and foreign_enum pragmas. Since such a pragma would convert an enum
    type into a non-enum type, this is needed to ensure that the code
    in add_foreign_enum.m that checks whether a type is an enum type
    is operating on data that is final. Without that, it may make
    wrong decisions.

compiler/make_hlds_separate_items.m:
compiler/add_pragma.m:
    Provide the support needed by the new code in make_hlds_passes.m.

    In add_pragma.m, rename some insts to avoid name ambiguities,
    and simplify an if-then-else.

compiler/hlds_module.m:
    Add two fields to exported_enum_infos, to make processing them easier.
    (We couldn't do this earlier, since add_foreign_enum.m didn't have
    access to the final forms of the bodies of du type definitions,
    which is where the values of the two new fields come from.)

compiler/export.m:
compiler/ml_type_gen.m:
    Simplify some code using the new fields in exported_enum_infos.

compiler/error_util.m:
    Provide a mechanism to control whether sym_names in cons_ids
    are module qualified or not. This is "needed" by the new error
    messages created in add_foreign_enum.m.

compiler/check_promise.m:
compiler/det_report.m:
compiler/parse_inst_mode_name.m:
compiler/typecheck_errors.m:
    Conform to the change to error_util.m.

compiler/make_tags.m:
    Clean up some code and some comments.

tests/invalid/exported_foreign_enum.{m,err_exp}:
    A new test case to test the new capability to print more than one
    error message for the same pragma.

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

tests/invalid/ee_invalid.err_exp:
    Expect improved error messages.
2017-06-05 12:34:58 +02:00
Zoltan Somogyi
56bff7fd6c Optimize the module_info structure.
And delete an old misleading comment.
2017-03-15 16:47:09 +11:00
Paul Bone
e2ffb8d01a Reorganise dependency graph code
This change moves code that could be generic/common out of
hlds_dependency_graph.m into dependency_graph.m.  It also moves some code
from hlds_module.m into hlds_dependency_graph.m where it makes more sense.

compiler/dependency_graph.m:
    New module.

    Make the accessors predicates functions and give them more sensible
    names.

    Create a new accessors to get a version or the dependency ordering,
    condensed into a single list.

compiler/hlds_dependency_graph.m:
    Build the dependency_info structure in a more straightforward way.  It
    can easily be created with a single call rather than three.  The
    dependency ordering information is now calculated by dependency_graph.m.

    Make build_dependency_graph, build_proc_dependency_graph and
    build_pred_dependency_graph functions rather than predicates.

compiler/hlds_module.m:
    As above.

compiler/closure_analysis.m:
compiler/deep_profiling.m:
compiler/deforest.m:
compiler/dep_par_conj.m:
compiler/exception_analysis.m:
compiler/granularity.m:
compiler/hlds_dependency_graph.m:
compiler/inlining.m:
compiler/lco.m:
compiler/libs.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mode_constraints.m:
compiler/par_loop_control.m:
compiler/rbmm.interproc_region_lifetime.m:
compiler/rbmm.points_to_analysis.m:
compiler/stratify.m:
compiler/structure_reuse.indirect.m:
compiler/structure_sharing.analysis.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_main.m:
compiler/termination.m:
compiler/trailing_analysis.m:
compiler/tupling.m:
    Conform to changes.
2017-02-16 12:41:51 +11:00
Zoltan Somogyi
95ff02b1bf Add options to check the ordering of module contents.
One option, --warn-non-contiguous-decls, generates warnings if the
mode declarations of a predicate or function aren't in a contiguous block
immediately following the pred or func declaration. Since this is a rare
kind of "style error", this option is enabled by default.

Two options, --warn-inconsistent-pred-order-clauses and
--warn-inconsistent-pred-order-foreign-procs, warn about inconsistencies
between (a) the order in which predicates (and functions) are declared,
and (b) the order in which they are defined. The two options differ in
their scope. The latter applies to all predicates and functions defined
in the module, while the former applies only to those whose definitions
include Mercury clauses.

Since an exported predicate or function may need nonexported auxiliary
predicates and/or functions, imposing a single order the declarations and
definitions of *all* the predicates and functions in a module is not a good
idea. Instead, both options divide the predicates and functions defined
in a module two groups, the exported and the nonexported, and expect
a consistent order only within each group.

The result is output that looks like this:

    time.m:021: Warning: the order of the declarations and definitions of the
    time.m:021:   exported predicates is inconsistent, as shown by this diff:
    time.m:021:
    time.m:021:   --- declaration order
    time.m:021:   +++ definition order
    time.m:021:   @@ -1,7 +1,7 @@
    time.m:021:    predicate `clock'/3
    time.m:021:   -predicate `time'/3
    time.m:021:    predicate `times'/4
    time.m:021:    function `clk_tck'/0
    time.m:021:   +predicate `time'/3
    time.m:021:    function `difftime'/2
    time.m:021:    predicate `localtime'/4
    time.m:021:    function `localtime'/1

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

compiler/style_checks.m:
    A new module that generates the new warnings if warranted.

compiler/check_hlds.m:
compiler/notes/compiler_design.html:
    Include and document the new module.

compiler/mercury_compile_front_end.m:
    Invoke the new module if any of the three new options is set.

compiler/hlds_pred.m:
    Record the item number of every predicate, function, and mode declaration
    in the module being compiled. We need this for information for the
    new warnings.

compiler/hlds_module.m:
    Record the context of the module declaration. We use this context
    for warnings about inconsistent order, since there isn't a better one.

compiler/hlds_clauses.m:
    Add a mechanism to retrieve the item numbers of a set of clauses
    even if they are contiguous.

    Document some old data types.

compiler/error_util.m:
    Add a new phase for style checks.

compiler/accumulator.m:
compiler/add_class.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_special_pred.m:
compiler/check_typeclass.m:
compiler/clause_to_proc.m:
compiler/from_ground_term_util.m:
compiler/lambda.m:
compiler/make_hlds.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/par_loop_control.m:
compiler/polymorphism.m:
compiler/stm_expand.m:
compiler/table_gen.m:
compiler/unify_proc.m:
    Conform the changes to the HLDS above.

compiler/typecheck_errors.m:
    Fix style of error messages.

library/array2d.m:
library/assoc_list.m:
library/benchmarking.m:
library/bit_buffer.write.m:
library/bool.m:
library/builtin.m:
library/construct.m:
library/cord.m:
library/counter.m:
library/float.m:
library/injection.m:
library/lazy.m:
library/lexer.m:
library/ops.m:
library/private_builtin.m:
library/profiling_builtin.m:
library/prolog.m:
library/queue.m:
library/rational.m:
library/require.m:
library/stack.m:
library/std_util.m:
library/store.m:
library/thread.semaphore.m:
library/tree234.m:
library/univ.m:
library/version_store.m:
    Move declarations or definitions around to avoid some of the warnings
    that we can now generate. (There are many more left.)

    Make some minor style improvements in the process.

tests/warnings/inconsistent_pred_order.{m,exp}:
tests/warnings/non_contiguous_decls.{m,exp}:
    New test cases to test the new options. They are both copies of
    tests/benchmarks/queens.m, with intentionally-screwed-up style.

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

tests/warnings/Mercury.options:
    Specify the options being tested for the new test cases.

tests/benchmarks/queens.m:
    Bring the style of this module up to date (before copying it).

tests/invalid/mode_decl_in_wrong_section.err_exp:
    Expect the warnings we now generate.
2016-10-15 17:26:32 +11:00
Julien Fischer
a7159f86b0 Minor cleanups.
library/private_builtin.m:
library/multi_map.m:
compiler/hlds_module.m:
    Fix spelling.

library/rtree.m:
    Delete redundant module qualification from clause heads.
2016-07-01 10:48:47 +10:00
Zoltan Somogyi
9d4f1e6ae5 Avoid using some Mercury keywords.
compiler/pred_table.m:
compiler/prog_data.m:
    Avoid using / as a function symbol.

    Rename some function symbols to avoid ambiguity.

compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_enum.m:
compiler/add_foreign_proc.m:
compiler/add_mode.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/check_for_missing_type_defns.m:
compiler/check_typeclass.m:
compiler/complexity.m:
compiler/det_report.m:
compiler/equiv_type.m:
compiler/error_util.m:
compiler/format_call.m:
compiler/hlds_error_util.m:
compiler/hlds_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/inst_check.m:
compiler/introduce_parallelism.m:
compiler/make_hlds_error.m:
compiler/make_hlds_passes.m:
compiler/make_tags.m:
compiler/mercury_to_mercury.m:
compiler/mode_errors.m:
compiler/modes.m:
compiler/module_qual.qual_errors.m:
compiler/oisu_check.m:
compiler/parse_mutable.m:
compiler/parse_sym_name.m:
compiler/parse_type_defn.m:
compiler/post_term_analysis.m:
compiler/prog_out.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/resolve_unify_functor.m:
compiler/type_constraints.m:
compiler/typecheck_errors.m:
compiler/unused_args.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.

    In a few places, improve the format of error messages.

tests/invalid/cyclic_typeclass.err_exp:
tests/invalid/cyclic_typeclass_2.err_exp:
tests/invalid/cyclic_typeclass_3.err_exp:
tests/warnings/inst_with_no_type.exp:
    Expect the updated error messages.
2016-05-13 11:46:37 +10:00