21 Commits

Author SHA1 Message Date
Zoltan Somogyi
3f72528869 Update module stability levels. 2025-08-11 22:32:52 +02:00
Zoltan Somogyi
53a27ea2e6 Explain a design decision. 2025-01-01 19:19:42 +11:00
Zoltan Somogyi
a9376f2bd3 Replace an if-then-else chain with two switches.
library/string.to_string.m:
    Replace a long series of dynamic cast tests with a switch on the
    id of the type of the value we are trying to convert to a string.
    Besides being clearer, the new code is also faster. To help the latter
    along, also change the code of det_dynamic_casts to avoid a memory
    allocation.

    In the process, fix an old oversight: treat int64 and uint64 values
    the same way as we treat other sized integers.

tests/hard_coded/uint64_switch_test.exp:
    Expect that updated treatment.
2025-01-01 18:59:27 +11:00
Zoltan Somogyi
685eefa206 Move base of term_io.m to X_to_string, write_X, format_X.
library/term_io.m:
    Move the base operations of term_io.m to the structure we use
    in parse_tree_out*.m in the compiler, where for every type X,
    there is a function X_to_string, and two predicates write_X and format_X,
    with the former operating on I/O states, and the latter operating on
    arbitrary streams. The idea is to apply the "don't repeat yourself"
    principle by having both X_to_string and write_X just call format_X.

    Apply that principle here as well, with one minor exception,
    which is that for some values of X, both write_X and format_X are
    implemented in terms of X_to_string.

    Impose the X_to_string, write_X, format_X naming scheme. The ancient code
    already in term_io.m had (each for some values of X) had

    - some of these functions/predicates missing
    - inconsistent names, in that write_X/N did I/O while write_X/(N+1)
      wrote to arbitrary streams
    - names that were inconsistent in another way, in that write_X/N did
      I/O of values of type X, but the function to convert X to string
      was NOT named X_to_string.

    Keep some of the misnamed functions around permanently, because
    some of the names for fitting into the new scheme, such as
    "escaped_string_to_string", would be strange.

    Keep the rest of the misnamed functions and all the misnamed predicates
    around temporarily, with commented-out obsolete pragmas. I expect
    to make these pragmas active when the rest of term_io.m is converted
    to this scheme.

    To prepare for that, use string.builder, not string, as the
    stream.writer instance to implement X_to_string, because of its
    better algorithmic complexity, which is needed mainly for terms
    of nontrivial size.

    Consistently put operations on each X in the order X_to_string,
    write_X and format_X.

NEWS.md:
    List all the new predicates and functions.

configure.ac:
    Require the installed compiler to contain the fix which allows
    a typespec pragma for an obsolete predicate or function.

browser/interactive_query.m:
compiler/hlds_out_util.m:
compiler/parse_tree_out_clause.m:
compiler/parse_tree_out_cons_id.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_out_pragma.m:
compiler/parse_tree_out_sym_name.m:
compiler/parse_tree_out_type_repn.m:
library/pretty_printer.m:
library/stream.string_writer.m:
library/string.builder.m:
mdbcomp/trace_counts.m:
    Update all references to the newly-obsolete predicates and functions.

library/string.to_string.m:
    Improve variable names.
2023-07-04 00:00:09 +02:00
Zoltan Somogyi
d481a42f59 Give each op class (infix, prefix etc) its own slot.
library/ops.m:
    Instead of an op_table mapping a string to a list of one or more op_infos,
    make it map the string to a single structure, the op_infos, which has
    four slots, one each for infix, binary prefix, prefix and postfix
    op information. This allows parsers and unparsers to go directly to
    the kind of operator (e.g. infix or prefix) that they are interested in.

NEWS:
    Announce the change.

compiler/parse_tree_out_term.m:
library/mercury_term_parser.m:
library/pretty_printer.m:
library/stream.string_writer.m:
library/string.to_string.m:
samples/calculator2.m:
tests/hard_coded/bug383.m:
    Conform to the change. In several places, the new operator representation
    allows the replacement of loops with direct lookups, and the replacement
    of if-then-else chains with switches.

    Add reminders about keeping two predicates in sync.
2022-11-14 13:46:22 +11:00
Zoltan Somogyi
c6d857cb6b Cleanups of ops-related code.
library/io.m:
    Delete the set_io_table predicate, which did nothing and was never
    called from anywhere, and the get_io_table predicate, which always
    returned the same op_table. They were in io.m's interface, but in the
    not-publicly-visible part of the interface.

library/ops.m:
    Rename the lookup_op method to is_op.

    Delete references to the predicates deleted from io.m.

NEWS:
    Announce the lookup_op->is_op rename.

compiler/parse_tree_out_term.m:
library/mercury_term_parser.m:
library/string.to_string.m:
library/term_io.m:
samples/calculator2.m:
tests/hard_coded/bug383.m:
    Conform to the lookup_op->is_op rename.

    Replace calls to get_io_table with code that directly gets
    the Mercury op table.

    In parse_tree_out_term.m, call the predicates operating on the
    Mercury op table directly, not through the op_table type class.

    In mercury_term_parser.m, update some comments.

    In term_io.m, use OpTable to refer to op_tables.

tests/hard_coded/stdlib_init.{m,exp}:
    Don't test get_io_table.
2022-11-12 12:53:07 +11:00
Zoltan Somogyi
5383f604df Eliminate some redundant computations.
Standardize on OpTable as the name of op tables.
2022-11-11 03:05:57 +11:00
Zoltan Somogyi
de75b98b18 Make higher operator priorities bind tighter.
Mercury inherited its original system of operator priorities from Prolog,
because during its initial development, we wanted to be able execute
the Mercury compiler using NU-Prolog and later SICStus Prolog.
That consideration has long been obsolete, and now we may fix the
design error that gifted Prolog with its counter-intuitive system
of operator priorities, in which higher *numerical* operator priorities
mean lower *actual* priorities. This diff does that.

library/ops.m:
    Change the meaning of operator priorities, to make higher numerical
    priorities mean also higher actual priorities.

    This semantic change requires corresponding changes in any other module
    that uses ops.m. To force this change to occur, change the type
    representing priorities from being a synonym for a bare int to being
    a notag wrapper around an uint.

    The old "assoc" type had a misleading name, since it is related to
    associativity but is not itself a representation of associativity.
    Its two function symbols, which used to be just "x" and "y", meant that
    the priority of an argument must be (respectively) greater than,
    or greater than equal to, the priority of the operator. So rename
    x to arg_gt, y to arg_ge, and assoc to arg_prio_gt_or_ge.

    Rename the old adjust_priority_for_assoc predicate to min_priority_for_arg,
    which better expresses its semantics. Turn it into a function, since
    some of its users want it that way, and move its declaration to the
    public part of the interface.

    Add a method named tightest_op_priority to replace the use of 0
    as a priority.

    Rename the max_priority method as the loosest_op_priority method.

    Add a method named universal_priority to replace the use of
    max_priority + 1 as a priority.

    Add a function to return the priority of the comma operator,
    to allow other modules to stop hardcoding it.

    Add operations for comparing priorities and for incrementing/decrementing
    priorities.

    Change the prefix on the names of the predicates that take op_infos
    as inputs from "mercury_op_table_" to "op_infos_", since the old prefix
    was misleading.

    Add a note on an significant old problem with an exported type synonym.

library/mercury_term_parser.m:
    Conform to the changes above.

    Delete unnecessary module qualifiers, since they were just clutter.

    Add "XXX OPS" to note further opportunities for improvement.

library/pprint.m:
    Conform to the changes above.

    Rename a function to avoid ambiguity.

library/pretty_printer.m:
library/stream.string_writer.m:
library/string.to_string.m:
library/term_io.m:
    Conform to the changes above.

library/string.m:
    Add a note on an significant old problem.

NEWS:
    Announce the user-visible changes.

tests/hard_coded/bug383.m:
    Update this test case to use the new system of operator priorities.

tests/hard_coded/term_io_test.{m,inp}:
    Fix white space.

extras/old_library_modules/old_mercury_term_parser.m:
extras/old_library_modules/old_ops.m:
    The old contents of the mercury_term_parser and ops modules,
    in case anyone wants to continue using them instead of updating
    their code to use their updated equivalents.

samples/calculator2.m:
    Import the old versions of mercury_term_parser and ops.
2022-11-11 00:11:44 +11: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
8ff61f8a4b Delete quotes from `VarNames' in stdlib comments.
In the Mercury standard library, every exported predicate or function
has (or at least *should* have) a comment that documents it, including
the meanings of its arguments. About 35-40% of these modules put `'s
(left and right quotes) around the names of the variable representing
those arguments. Some tried to do it consistently (though there were spots
with unquoted or half quoted names), while some did it only a few places.
This is inconsistent: we should either do it everywhere, or nowhere.
This diff makes it nowhere, because

- this is what the majority of the standard library modules do;
- this is what virtually all of the modules in the compiler, profiler,
  deep_profiler etc directories do;
- typing all those quotes when adding new predicates in modules that
  follow this convention is a pain in the ass; and because
- on many modern terminals, `' looks non-symmetrical and weird.

Likewise, the comment explaining a predicate often started with

    % `predname(arguments)' returns ...

This diff deletes these quotes as well, since they add nothing useful.

This diff does leave in place quotes around code fragments, both terms
and goals, where this helps delineate the boundaries of that fragment.
2022-03-07 11:49:00 +11:00
Zoltan Somogyi
06f81f1cf0 Add end_module declarations ...
.. to modules which did not yet have them.
2022-01-09 10:36:15 +11:00
Zoltan Somogyi
5f63c4ce0d Delete unused imports. 2019-06-26 23:41:16 +02:00
Mark Brown
d465fa53cb Update the COPYING.LIB file and references to it.
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.

COPYING.LIB:
    Add a special linking exception to the LGPL.

*:
    Update references to COPYING.LIB.

    Clean up some minor errors that have accumulated in copyright
    messages.
2018-06-09 17:43:12 +10:00
Zoltan Somogyi
74a7a8345c Fix too-long lines. 2017-12-30 19:59:59 +11:00
Julien Fischer
3f28b096ef Add builtin 8, 16 and 32 bit integer types -- Part 2.
Enable support for literals of the new types.

Begin implementing library support for 8, 16, and 32 bit types.

Update the compiler to represent values of their own constants.

library/int8.m:
library/int16.m:
library/int32.m:
library/uint8.m:
library/uint16.m:
library/uint32.m:
    Begin filling these modules out.

library/uint.m:
    Unrelated change: add the predicates plus/2, minus/2 and
    times/2 for uints.

library/integer.m:
    Add predicates for converting integer/0 values into values
    of the new types.

    Add functions for converting values of the new types into
    integer/0 values.

library/string.m:
    Add functions for converting values of the new types to strings.

library/private_builtin.m:
    Replace the placeholder definitions for the builtin unify and compare
    predicates for the new types with their actual definitions.

library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
    Replace placeholder definitions for the new types with their
    actual definitions.

library/io.m:
    Add predicates for writing values of the new types to file streams.

library/stream.string_writer.m:
    Implement generic write and print for values of the new types.

library/string.to_string.m:
    Likewise for string/1.

library/term.m:
library/term_conversion.m:
    Add predicates and functions for converting the new types to
    and from terms.

compiler/builtin_ops.m:
compiler/elds.m:
compiler/hlds_data.m:
compiler/llds.m:
compiler/mlds.m:
compiler/prog_data.m:
    Replace placeholders for the new types with the new types.

compiler/superhomogeneous.m:
    Enable literals of the new types.

compiler/mlds_to_cs.m:
    Avoid a warning from the C# compiler for bitwise-or operators
    with sbyte operands.

compiler/c_util.m:
compiler/elds_to_erlang.m:
compiler/hlds_out_util.m:
compiler/llds_out_data.m:
compiler/lookup_switch.m:
compiler/mlds_to_c.m:
compiler/mlds_to_java.m:
compiler/opt_debug.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_to_term.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_util.m:
    Replace placeholder code for the new types with code that uses the new
    types.

tests/invalid/invalid_int.m:
tests/invalid/invalid_int.err_exp2:
    Extend this test case to cover the fixed size integer types.
2017-08-21 09:50:16 +10:00
Julien Fischer
e9b0c489d2 Two fixes for uint support.
1. Fix an abort in the MLDS backend involving switches on uints.

2. Make string.string/1 handle uints.

compiler/ml_switch_gen.m:
    Handle uints properly in a spot.

library/string.to_string.m:
     Make string.string/1 handle uint values.

tests/hard_coded/Mmakefile:
tests/hard_coded/uint_switch_test.{m,exp}:
     Add a test case.
2017-05-24 09:59:01 +10:00
Zoltan Somogyi
0204f171f1 Delete unneeded import. 2016-02-23 06:09:55 +11:00
Zoltan Somogyi
44f9f1f405 Convert (C->T;E) to (if C then T else E). 2015-12-01 07:58:07 +11:00
Zoltan Somogyi
62ec97d443 Report imports shadowed by other imports.
If a module has two or more import_module or use_module declarations
for the same module, (typically, but not always, one being in its interface
and one in its implementation), generate an informational message about
each redundant declaration if --warn-unused-imports is enabled.

compiler/hlds_module.m:
    We used to record the set of imported/used modules, and the set of
    modules imported/used in the interface of the current module. However,
    these sets

    - did not record the distinction between imports and uses;
    - did not allow distinction between single and multiple imports/uses;
    - did not record the locations of the imports/uses.

    The first distinction was needed only by module_qual.m, which *did*
    pay attention to it; the other two were not needed at all.

    To generate messages for imports/uses shadowing other imports/uses,
    we need all three, so change the data structure storing such information
    for *direct* imports to one that records all three of the above kinds
    of information. (For imports made by read-in interface and optimization
    files, the old set of modules approach is fine, and this diff leaves
    the set of thus *indirectly* imported module names alone.)

compiler/unused_imports.m:
    Use the extra information now available to generate a
    severity_informational message about any import or use that is made
    redundant by an earlier, more general import or use.

    Fix two bugs in the code that generated warnings for just plain unused
    modules.

    (1) It did not consider that a use of the builtin type char justified
    an import of char.m, but without that import, the type is not visible.

    (2) It scanned cons_ids in goals in procedure bodies, but did not scan
    cons_ids that have been put into the const_struct_db. (I did not update
    the code here when I added the const_struct_db.)

    Also, add a (hopefully temporary) workaround for a bug in
    make_hlds_passes.m, which is noted below.

    However, there are at least three problems that prevent us from enabling
    --warn-unused-imports by default.

    (1) In some places, the import of a module is used only by clauses for
    a predicate that also has foreign procs. When compiled in a grade that
    selects one of those foreign_procs as the implementation of the predicate,
    the clauses are discarded *without* being added to the HLDS at all.
    This leads unused_imports.m to generate an uncalled-for warning in such
    cases. To fix this, we would need to preserve the Mercury clauses for
    *all* predicates, even those with foreign procs, and do all the semantic
    checks on them before throwing them away. (I tried to do this once, and
    failed, but the task should be easier after the item list change.)

    (2) We have two pieces of code to generate import warnings. The one in
    unused_imports.m operates on the HLDS after type and mode checking,
    while module_qual.m operates on the parse tree before the creation of
    the HLDS. The former is more powerful, since it knows e.g. what types and
    modes are used in the bodies of predicates, and hence can generate warnings
    about an import being unused *anywhere* in a module, as opposed to just
    unused in its interface.

    If --warn-unused-imports is enabled, we will get two separate set of
    reports about an interface import being unused in the interface,
    *unless* we get a type or mode error, in which case unused_imports.m
    won't be invoked. But in case we do get such errors, we don't want to
    throw away the warnings from module_qual.m. We could store them and
    throw them away only after we know we won't need them, or just get
    the two modules to generate identical error_specs for each warning,
    so that the sort_and_remove_dups of the error specs will do the
    throwing away for us for free, if we get that far.

    (3) The valid/bug100.m test case was added as a regression test for a bug
    that was fixed in module_qual.m. However the bug is still present in
    unused_imports.m.

compiler/make_hlds_passes.m:
    Give hlds_module.m the extra information it now needs for each item_avail.

    Add an XXX for a bug that cannot be fixed right now: the setting of
    the status of abstract instances to abstract_imported. (The "abstract"
    part is correct; the "imported" part may not be.)

compiler/intermod.m:
compiler/try_expand.m:
compiler/xml_documentation.m:
    Conform to the change in hlds_module.m.

compiler/module_qual.m:
    Update the documentation of the relationship of this module
    with unused_imports.m.

compiler/hlds_data.m:
    Document a problem with the status of instance definitions.

compiler/hlds_out_module.m:
    Update the code that prints out the module_info to conform to the change
    to hlds_module.m.

    Print status information about instances, which was needed to diagnose
    one of the bugs in unused_imports.m. Format the output for instances
    nicer.

compiler/prog_item.m:
    Add a convenience predicate.

compiler/prog_data.m:
    Remove a type synonym that makes things harder to understand, not easier.

compiler/modules.m:
    Delete an XXX that asks for the feature this diff implements.
    Add another XXX about how that feature could be improved.

compiler/Mercury.options.m:
    Add some more modules to the list of modules on which the compiler
    should be invoked with --no-warn-unused-imports.

compiler/*.m:
library/*.m:
mdbcomp/*.m:
browser/*.m:
deep_profiler/*.m:
mfilterjavac/*.m:
    Delete unneeded imports. Many of these shadow other imports, and some
    are just plain unneeded, as shown by --warn-unused-imports. In a few
    modules, there were a *lot* of unneeded imports, but most had just
    one or two.

    In a few cases, removing an import from a module, because it *itself*
    does not need it, required adding that same import to those of its
    submodules which *do* need it.

    In a few cases, conform to other changes above.

tests/invalid/Mercury.options:
    Test the generation of messages about import shadowing on the existing
    import_in_parent.m test case (although it was also tested very thoroughly
    when giving me the information needed for the deletion of all the
    unneeded imports above).

tests/*/*.{m,*exp}:
    Delete unneeded imports, and update any expected error messages
    to expect the now-smaller line numbers.
2015-08-25 00:38:49 +10:00
Zoltan Somogyi
7f9791aa26 Standardize divider line lengths in the library.
library/*.m:
    As above.

tool/stdlines:
    A new shell script to do the job.
2014-11-23 22:05:34 +11:00
Zoltan Somogyi
50c1e04480 Carve two submodules out of string.m.
There are no algorithmic changes, though there are some name changes.

library/string.format.m:
    New submodule of string.m. Contains the parts of old string.m
    that implement string.format. About 1500 lines.

library/string.to_string.m:
    New submodule of string.m. Contains the parts of old string.m
    that implement string.string, string.string_ops and
    string.string_ops_noncanon. About 500 lines.

library/string.m:
    Replace the code that is now in the new submodules with includes
    of those submodules.

library/library.m:
    List the two new submodules. Fix some bitrot about where
    new library modules may need to be listed.

doc/Mmakefile:
    Do not document the two new submodules, since they are implementation
    details.
2014-11-10 14:31:51 +11:00