Commit Graph

688 Commits

Author SHA1 Message Date
Zoltan Somogyi
c69b7e4b9a Add "did you mean ..." to undef pred reports.
compiler/typecheck_error_undef.m:
    If we are reporting an error for a reference to an undefined predicate,
    check whether any predicates exist whose names are "close enough"
    to the name of the referenced predicate, and if yes, add to the
    error message a line containing "(Did you mean x, y or z?)".

    (Doing the same for references to undefined functions is future work.
    The two are separate because things that look like function references
    can also refer to e.g. data constructors.)

library/edit_distance.m:
    Add this new module to implement the "close enough" check.
    This new module is similar to the existing edit_seq.m module,
    but it is designed to serve different requirements, and it seems to me
    to be far from trivial to write code to meet both sets of requirements
    at once.

library/library.m:
library/MODULES_DOC:
    Include the new module in the standard library.

NEWS.md:
    Announce the new library module.

tests/hard_coded/edit_distance_test_closest.{m,exp}:
tests/hard_coded/edit_distance_test_cost.{m,exp}:
    Two new test cases, each of which tests one of the two predicates
    exported by the new library module.

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

tests/invalid/qual_basic_test2.err_exp:
tests/invalid/types2.err_exp:
tests/invalid/undef_symbol.err_exp:
tests/invalid_submodules/undef_mod_qual.err_exp:
    Expect the new "did you mean" additions to error messages.
2023-09-26 00:56:19 +10:00
Zoltan Somogyi
88d4bccdba Add new optimization option --split-switch-arms.
Given a switch arm that matches several cons_ids, and which contains
one or more switches on the *same* variable, such as the arm for
f1/f2/f3/f4 below,

    (
        (X = f1 ; X = f2 ; X = f3 ; X = f4),
        ...
        (
            X = f1,
            ...
        ;
            (X = f2 ; X = f3),
            ...
        ;
            X = f4,
            ...
        ),
        ...
    ;
        ...
    )

this new optimization

- partitions the set of cons_id in that arm (in this case, {f1,f2,f3,f4})
  as finely as needed by any other the switches on X in that arm
  (in this case, that is three partitions containing {f1}, {f2,f3} and {f4}),

- splits that original switch arm into N arms, one arm for each partition,
  making a copy of the switch arm's goal for each partition,

- restricts any switches on the original switch variable (in this case, X)
  inside the copy of the arm goal inside each new case to only the cons_ids
  in that case's partition, and then replacing any resulting one-arm switches
  with the just goal inside that one arm.

The code resulting from these three steps will include some code duplication
(some of the pieces of code denoted by ... in the example above would be
duplicated), but it will need to execute fewer transfers of control.
This is worthwhile because (a) the branch instructions used to implement
switches are hard to predict unless most paths through the nested switches
are rarely if ever taken, and (b) the pipeline breaks caused by branches
that are not correctly predicted are one of the two major contributors
to the runtime of Mercury programs. (The other major contributors are
data cache misses.)

The implementation of this option has two major parts.

- Part 1 consists of discovering whether a procedure body contains
  any code in which a switch on a variable is nested inside an arm
  of another switch on that same variable. For any instance of such
  a pair of switches, it records the identity of the variable and
  the set of cons_ids of the outermost arm.

- Part 2 consists of actually transforming the procedure body
  by splitting each outermost switch arm thus recorded. (This part
  contains all three of the steps above.)

We integrate part 1 with the usual procedure body traversal of the
simplification pass, which makes it quite cheap. In most procedure bodies,
it won't find any nested switches meeting its criteria. We execute part 2,
which is relatively expensive, only if it does.

compiler/simplify_info.m:
    Add a new type, switch_arm, which represents one arm of a switch.

    Add a new field to the simplify_nested_context type. Its type
    is list(switch_arm), and it represents the stack of switch arms (if any)
    that the goal currently being simplified is inside. simplify_goal_switch.m
    uses this field to detect switches that occur inside an arm of an
    ancestor goal that is also a switch on the same variable.

    Add a new field to the simplify_info, a set of switch_arms,
    that denotes the set of switch arms from which that detection
    has actually happened, and which should therefore be
    partitioned and split.

compiler/simplify_goal_switch.m:
    Add the code for doing the detection and recording mentioned just above.
    This is the Part 1 mentioned above.

compiler/split_switch_arms.m:
    This new module implements the splitting up process.
    This is the Part 2 mentioned above.

compiler/simplify.m:
    Include the new module in the simplify subpackage of the check_hlds
    package.

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

compiler/simplify_proc.m:
    Invoke split_switch_arms.m (part 2) if the part of simplify_goal_switch.m
    implementing part 1 has found any work for it to do.

compiler/simplify_tasks.m:
    Add split_switch_arms as one of the tasks that simplification
    may be asked to do. Set its default value from the value of
    a new optimization option that, when specified, calls for it to be done.

compiler/options.m:
    Add this option, --split-switch-arms.

    Change the internal name of an existing option,
    everything_in_one_c_function, to the one expected by
    tools/make_optimization_options_middle.

    Replace the part of this file that is constructed by
    tools/make_optimization_options_middle.

doc/user_guide.texi:
    Document the new option.

tools/make_optimization_options_db:
    Add --split-switch-arms to the optimization tuple.

    Fix software rot by

    - renaming optimize_tailcalls to optimize_mlds_tailcalls inside the
      optimization tuple, as it has been in options.m, and

    - deleting erlang_switch_on_strings_as_atoms from the opt_tuple,
      as it has been from options.m.

tools/make_optimization_options_end:
    Enable the new option by default at optimization level 2.

tools/make_optimization_options_middle:
    Fix bugs in this script, which generates compiler/optimization_options.m.

    One bug was that it referred to the opt_level and opt_space options
    by the wrong name (optopt_level and optopt_space respectively).
    The other bug was that it expected opt_level to be a string_special option,
    when it is an int_special option.

    Make the handler_file this script generates easier to put into options.m
    by not generating a line that (a) already exists in options.m, and
    (b) would need to have a comma put after it, if one wanted this line
    to replace the copy already in options.m.

compiler/optimization_options.m:
    Rebuild this file after the changes above.

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

compiler/inst_merge.m:
    Mark two predicates, inst_merge_[34], to be inlined. The intention
    is that inst_merge_4 should be inlined into inst_merge_3, and then
    inst_merge_3 should be inlined inside inst_merge_2; that would then
    generate six levels of switches, three on one of the insts to be
    merged and three on the other, which the new optimization could
    then flatten. Unfortunately, inlining does not do this yet.

tests/hard_coded/test_split_switch_arms.{m,exp}:
    A new test case for the the new transformation.

tests/hard_coded/Mmakefile:
tests/hard_coded/Mercury.options:
    Enable the new test case, and specify the new option for it.
2023-07-24 19:14:17 +02:00
Julien Fischer
8032229faa Fix a typo.
tests/hard_coded/Mmakefile:
    As above.
2023-07-12 01:42:31 +10:00
Julien Fischer
7d5bd151be Fix tests/hard_coded/nonascii with MSVC.
tests/hard_coded/Mmakefile:
    Invoke cl appropriately to compile nonascii_gen.

    Handle the .exe extension where necessary.

tests/DEFNS_FOR_TESTS.in:
    Add a variable that says of we are using MSVC.
2023-07-11 17:17:03 +10:00
Zoltan Somogyi
2bd7c5ee3e Rename X's aux modules as X_helper_N in hard_coded.
tests/hard_coded/*.m:
    Rename modules as mentioned above.

    In a few cases, where the main module's name itself had a suffix,
    such as "_mod_a" or "_main", remove that suffix. This entails
    renaming the .exp file as well. (In some cases, this meant that
    the name of a helper module was "taken over" by the main module
    of the test case.)

    Update all references to the moved modules.

    General updates to programming style, such as

    - replacing DCG notation with state var notation
    - replacing (C->T;E) with (if C then T else E)
    - moving pred/func declarations to just before their code
    - replacing io.write/io.nl sequences with io.write_line
    - replacing io.print/io.nl sequences with io.print_line
    - fixing too-long lines
    - fixing grammar errors in comments

tests/hard_coded/Mmakefile:
tests/hard_coded/Mercury.options:
    Update all references to the moved modules.

    Enable the constant_prop_int test case. The fact that it wasn't enabled
    before is probably an accident. (When constant_prop_int.m was created,
    the test case was added to a list in the Mmakefile, but that list
    was later removed due to never being referenced.)

tests/hard_coded/constant_prop_int.{m,exp}:
    Delete the calls to shift operations with negative shift amounts,
    since we have added a compile-time error for these since the test
    was originally created.
2023-06-16 08:33:22 +02:00
Zoltan Somogyi
80b1d4a7e3 Test all bitset implementation at once.
library/test_bitset.m:
    Instead of comparing just one bitset module (tree_bitset by default)
    against set_ordlist, compare all of them (tree_bitset, sparse_bitset,
    and fat_sparse_bitset) against set_ordlist.

tests/hard_coded/test_bitsets.{m,exp}:
    Rename this test case from test_tree_bitset to test_bitsets, since
    (through library/test_bitset.m) we now test ALL bitset implementations,
    not just tree_bitset.

tests/hard_coded/Mmakefile:
    Refer to the test by its new name.
2023-01-29 04:04:24 +11:00
Julien Fischer
bbff6f8609 Fix a bug in string.format.
The current implementation of the unsigned conversion specifiers (i.e. %x, %X,
%o, %u) for fixed-size 8-, 16- and 32-bit signed integers works by casting
theses values into (word-sized) ints and then using the existing code for
formatting ints as unsigned values. This does not work for negative values as
they are being sign extended when converted to ints. For example,

      io.format("%x", [i8(min_int8)], !IO)

prints:

      ffffffffffffff80 (on a 64-bit machine)

rather than just:

      80

Fix the above problem by casting ints, int8s, int16s etc. that are being
formatted as unsigned values to uints and using the uint formatting code.

NOTE: the formatting code for 64-bit integers follows a different code path
and is not affected by any of this.

library/string.format.m:
    Implement unsigned conversion specifiers for non-64-bit signed
    integers by casting to uint and using the uint formatting code.

    Add predicates for converting signed integers into uints.

    The format_unsigned_int_* predicates can be deleted after this change
    is installed.

compiler/format_call.m:
    Implement unsigned conversion specifiers for non-64-bit signed
    integers by casting to uint and using the uint formatting code.

compiler/introduced_call_table.m:
    Update the table of introduced predicates.

compiler/options.m:
    Add an option that can be used to test whether this fix is
    installed.

tests/hard_coded/Mmakefile:
tests/hard_coded/Mercury.options:
tests/hard_coded/opt_format_sign_extend.{m,exp}:
    Test that formatting code introduced by the compiler does not
    accidentally sign-extend negative values.

tests/string_format/string_format_{o,x,u}.{m,exp,exp2}:
    Make these tests much more comprehensive then they previously
    were.
2023-01-27 17:16:54 +11:00
Julien Fischer
97735d9630 Do not allow std_util.pow/3 with negative values.
library/std_util.m:
    Make std_util.pow/3 throw an exception if it is called with a negative
    integer as its second argument.

tests/hard_coded/Mmakefile:
tests/hard_coded/func_exp.{m,exp}:
    Add a test of pow/3.

NEWS:
    Announce the above change.
2023-01-11 17:10:00 +11:00
Peter Wang
fba3fda155 Fix digraph.tc and digraph.rtc.
The implementation of digraph.rtc was incorrect (as demonstrated in the
new test case), which meant that digraph.tc was also incorrect.

library/digraph.m:
    Fix the implementation of rtc (reflexive transitive closure):

    - Following the algorithm used in digraph.cliques, it needs to
      traverse the graph G in *reverse* depth-first order.

    - To find the clique containing a vertex X, it needs to do a DFS on
      the *reversed* graph to find the vertices with a path to X.
      The vertices that were previously unvisited will be members of
      the same clique as X.

    - Previously it found the "followers" of the elements of the clique,
      and the followers of those followers, then added edges from the
      members of the current clique to those followers. However, that
      only includes vertices two steps removed from the clique.
      I have fixed it to add edges to *all* vertices reachable from
      members of the clique.

    Add straightforward implementations of tc and rtc for comparison.

    Add some comments.

tests/hard_coded/Mmakefile:
tests/hard_coded/digraph_tc.exp:
tests/hard_coded/digraph_tc.inp:
tests/hard_coded/digraph_tc.m:
    Add test case.

NEWS:
    Announce the fixes.
2023-01-11 11:04:26 +11:00
Julien Fischer
5274170784 Make characters an instance of the uenum typeclass
The recent change to sparse_bitsets broke the lex library in extras.
Specifically, we now now need to make characters an instance of the
uenum typeclass. This diff does so.

library/char.m:
     Add predicates and functions for converting between unsigned integers
     and characters.

     Make characters an instance of the uenum typeclass.

tests/hard_coded/Mmakefile:
tests/hard_coded/char_uint_conv.{m,exp,exp2}:
     Add a test of the above conversions.

NEWS:
     Announce the additions.

extras/lex/lex.m:
     Conform to recent changes.
2022-12-20 20:18:54 +11:00
Zoltan Somogyi
91864db2cd Rename the uint_bitwise.m test case ...
... to bitwise_uint.m, to fit in with

    bitwise_int.m
    bitwise_int{8,16,32,64}.m and
    bitwise_uint{8,16,32,64}.m.
2022-12-05 19:54:41 +11:00
Zoltan Somogyi
ec20b1ed0a Make sparse_bitset.m operate on uints.
NEWS:
    Mention all the user-visible changes below.

library/enum.m:
    Add the typeclass uenum, which is a version of the existing enum typeclass
    that maps items to uints, not ints. It also uses a semidet predicate,
    not a semidet function, to get back to the item from the uint.

library/sparse_bitset.m:
library/fat_sparse_bitset.m:
    Make these modules operate on uints, which means requiring the items
    in the sets to be instances of uenum, not enum.

    If a few places, improve loops by doing previously-repeated conversions
    of [u]ints into <offset, bit-to-set> pairs just once.

library/counter.m:
    Define ucounters, which allocate uints. Improve documentation.

library/digraph.m:
    Change digraph_keys from ints to uints, since we put them into
    sparse_bitsets.

library/int.m:
    Make int an instance of the uenum typeclass. This can help users
    who currently put ints into sparse_bitsets.

library/pprint.m:
    Prettyprint sparse_bitsets as lists of uints.

library/term.m:
    Make vars instances of uenum as well as enum.

library/uint.m:
    Make uint an instance of the uenum typeclass.

    Add the ubits_per_uint function, which allows some casts to be avoided.

compiler/make.deps_set.m:
    Change the indexes we put into sparse_bitsets from ints to uints.

compiler/make.make_info.m:
    Change the source of those indexes from ints to uints.

compiler/make.top_level.m:
compiler/make.util.m:
    Conform to the changes above.

compiler/pre_quantification.m:
    Change zones from ints to uints, since we put them into sparse_bitsets.

tests/hard_coded/int_uenum.{m,exp}:
tests/hard_coded/Mmakefile:
    Enable the new test case.

tests/valid/use_import_only_for_instance.m:
    Update this extract from library/digraph.m the same way as
    library/digraph.m itself.
2022-12-05 09:45:11 +11:00
Peter Wang
c8a5a7755d Delete unnecessary conditions on hard_coded/parse.
We don't need to prevent building the 'parse' test on platforms that
don't support static linking any more, as the static linking aspect of
that test case was disabled in commit fd088a4f6.

tests/hard_coded/Mmakefile:
    Delete conditions to avoid static linking on some platforms.

    Rename STATIC_LINK_PROGS to DEBUG_PROGS.
2022-11-23 16:48:31 +11:00
Peter Wang
7362493e1c Skip or delete tests that fail in low-level parallel grades.
Since the compiler now refuses to allow debugging in parallel grades,
tests that require debugging need to be skipped over in low-level
parallel grades or deleted.

tests/hard_coded/Mmakefile:
    Disable 'parse' test in parallel grades as it happens to link with
    debug libraries.

tests/par_conj/Mercury.options:
tests/par_conj/Mmakefile:
tests/par_conj/par_ddeath.exp:
tests/par_conj/par_ddeath.m:
tests/par_conj/par_ddeath_2.exp:
tests/par_conj/par_ddeath_2.m:
    Delete par_ddeath and par_ddeath_2 tests that once triggered a
    compiler abort with --trace deep in parallel grades.
    I don't think there is much value in keeping them around.

tests/valid/Mmake.valid.common:
    Skip LLDS_PROGS (i.e. test cases that required debugging) in
    parallel grades.

tests/valid/Mercury.options:
tests/valid/Mmakefile:
tests/valid/untuple_bug.m:
    Delete untuple_bug. It tests an old bug in the untupling
    transformation, which was more a programming exercise than something
    that should be used anyway.
2022-11-23 16:15:59 +11:00
Peter Wang
064e9ddf1d Add regression test for maybe_int/maybe_string options.
tests/hard_coded/.gitignore:
tests/hard_coded/Mmakefile:
tests/hard_coded/getopt_maybe_option.exp:
tests/hard_coded/getopt_maybe_option.m:
    Add test case for preceding fix for maybe_string options.
2022-11-08 17:14:25 +11:00
Zoltan Somogyi
fa14feedf0 Speed up pretty_printing a *lot*.
library/pretty_printer.m:
    Replace the indent_stack data structure with one that

    - can represent deep indentation in a compact data structure,
      as long as that indentation consists only of standard indents, and

    - can tell you how many code points the current indent stack consists of
      *without* counting the code points in all the individual indent pieces
      every time.

    This yields a big speedup, because the code used to spend a very large
    fraction of its time (between 40 and 50%) just counting the code points
    in indentation. This was on stress test data which had very deep
    indentation, but the cost would have been substantial even on moderately
    indented docs.

    Now that the indent_stack can represent more than one level of indentation
    in one data structure, print up to 30 levels of standard indentation
    with just one call to stream.put. By amortizing the overheads of stream.put
    over a must larger part of the output, this also yields a significant
    speedup.

    Move the indent_stack type and its (significantly expanded) set of
    operations to after the code that outputs docs, since it is just an
    implementation detail (though as explained above, an important detail).

tests/hard_coded/pretty_printer_stress_test.{m,data,exp}:
    A stress test for the pretty_printer whose profiling lead to the
    identification of the performance problems fixed above.

tests/hard_coded/Mmakefile:
    Enable the new test case, now that it is not too expensive to run
    on every bootcheck.
2022-08-30 13:35:54 +10:00
Peter Wang
2ff6b119ef Fix some handling of ill-formed sequences in string module.
library/string.m:
    Fix string.all_match to fail if the string being tested contains
    any ill-formed code unit sequences.

    Fix the Mercury implementation of string.contains_char to continue
    searching for the character past any ill-formed code unit sequences.
    The foreign code implementations already did so.

    Fix unsafe_index_next_repl and unsafe_prev_index_repl in C grades.
    We indexed the C string with `ReplacedCodeUnit = Str[Index]' but
    since Mercury strings have the C type `char *', ReplacedCodeUnit
    could take on a negative value. When ReplacedCodeUnit == -1,
    the caller would assume there is a valid encoding of a code point
    beginning at Index, and therefore return `not_replaced' instead of
    `replaced_code_unit(255)'.

    Add casts to `unsigned char' in other places where we index C
    strings.

    Clarify documentation.

    Document that string.duplicate_char may throw an exception.

tests/hard_coded/string_all_match.m:
tests/hard_coded/string_all_match.exp:
tests/hard_coded/string_all_match.exp2:
    Add test for string.all_match.

tests/hard_coded/contains_char_2.m:
tests/hard_coded/contains_char_2.exp:
    Delete older test case for string.contains_char.

tests/hard_coded/string_contains_char.m:
tests/hard_coded/string_contains_char.exp:
tests/hard_coded/string_contains_char.exp2:
    Add better test for string.contains_char.

tests/hard_coded/Mmakefile:
    Enable the tests.

NEWS:
    Announce the changes.
2022-07-27 14:56:49 +10:00
Julien Fischer
ae0525af53 Add string.contains_match/2.
Add a new predicate that tests if string contains any characters that succeed
for a given test predicate.

library/string.m:
    Add the new predicate.

compiler/options.m:
    Replace the predicate string_contains_whitespace/1 defined here
    with a call to the new library predicate.

NEWS:
    Announce the new predicate.

tests/hard_coded/Mmakefile:
tests/hard_coded/string_contains_match.{m,exp}:
    Add a test of the new predicate.
2022-07-25 19:38:01 +10:00
Zoltan Somogyi
3459266a7a Carve stdlib module ra_list.m out of bt_array.m.
library/ra_list.m:
    As above.

    Rename ra_list_lookup to ra_list_search, since it fails if the item
    to be accessed does not exist. Add a version, ra_list_lookup, which
    aborts in that case.

    Add predicates to append two ra_lists, and to convert ra_lists
    to just plain lists.

    Change the argument order of some predicates to be more
    state variable friendly.

    Add some documentation.

library/bt_array.m:
    Delete the moved code, and update the references to the changed predicates.

library/Mercury.options:
    Now that the ra_list predicates have been moved to their own module,
    stop giving bt_array.m a free pass on inconsistent predicate order.

library/MODULES_DOC:
library/library.m:
    Add ra_list.m as a documented module of the Mercury standard library.

library/array.m:
    Delete a predicate that served as a test for an ancient bug fix.

NEWS:
    Announce both the new ra_list module, and the deletion of the predicate
    from array.m.

tests/hard_coded/array_sort.m:
    Don't call the predicate deleted from array.m.

tests/hard_coded/ra_list_test.{m,exp}:
    A new test case to test operations on ra_lists.

tests/hard_coded/Mmakefile:
    Enable the new test case.
2022-06-11 11:11:30 +10:00
Julien Fischer
5f5c67b281 Add more operations on cords.
library/cord.m:
    Add is_singleton/2, foldr2/6 and foldr3/8.

NEWS:
     Announce the above additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/test_cord3.{m,exp}:
     Add a test of is_singleton/2 (and is_empty/1).
2022-06-07 16:37:45 +10:00
Peter Wang
1b7e5adecf Don't use __builtin_setjmp, __builtin_longjmp on AArch64 with older GCCs.
There is an issue on Linux/aarch64 with older versions of gcc where a
commit performed on a thread using the gcc __builtin_longjmp function
causes an assertion failure in pthread_create() if the Mercury runtime
is dynamically linked:

    pthread_create.c:430: start_thread: Assertion `freesize < pd->stackblock_size' failed.

or a crash if the Mercury runtime is statically linked:

    *** Mercury runtime: caught segmentation violation ***
    cause: address not mapped to object

The gcc versions tested are:

    BAD - gcc version 6.3.0 20170516 (Debian 6.3.0-18) from Debian 9
    BAD - gcc version 8.3.0 (Debian 8.3.0-2) from Debian 10
    OK  - gcc version 10.2.1 20210110 (Debian 10.2.1-6) from Debian 11

on Debian with glibc.

runtime/mercury.h:
    Define MR_USE_GCC_BUILTIN_SETJMP_LONGJMP if we decide to use gcc's
    __builtin_setjmp and __builtin_longjmp functions instead of the
    standard functions.

    Use standard setjmp/longjmp on aarch64 if gcc version is < 10.

    Update the comment for MR_builtin_jmp_buf to refer to the GCC manual
    instead of the GCC source code. Use an array of 'intptr_t's instead
    of 'void *'s, to match the manual.

tests/hard_coded/Mmakefile
tests/hard_coded/thread_commit.m:
tests/hard_coded/thread_commit.exp:
tests/hard_coded/thread_commit.exp2:
    Add test case.
2022-05-26 12:47:21 +10:00
Zoltan Somogyi
b96a90f948 Parse disjunctions using tail recursive code ...
to allow even very long disjunctions to be parsed in constant stack space.
This fixes Mantis bug #559.

compiler/prog_item.m:
    We used to represent a disjunction like ( GoalA ; GoalB ; GoalC ; GoalD )
    in the parse tree as

        disj_expr(ContextA, GoalA,
            disj_expr(ContextB, GoalB,
                disj_expr(ContextC, GoalC,
                    GoalD)))

    To enable the changes in parse_goal.m and parse_dcg_goal.m, switch over
    to representing them as

        disj_expr(ContextA, GoalA, GoalB, [GoalC, GoalD])

    The type of this term enforces the invariant that a disjunction
    must have at least two disjuncts.

    The fact that this throws away ContextB and ContextC is not a problem;
    they were never used, being thrown away when converting the parse tree
    to the HLDS.

compiler/parse_goal.m:
compiler/parse_dcg_goal.m:
    After seeing the first comma in the above disjunction, these parsers
    used to (1) parse its left operand, GoalA, (2) parse its right operand,
    ( GoalB ; GoalC ; GoalD), and then (3) check for errors. This code
    was prevented from being tail recursive both by the presence of step 3,
    and the fact that step 2 indirectly invokes another predicate that
    (until my previous change to parse_goal.m) had a different determinism.

    Fix the first issue by having the new predicate parse_goal_disjunction,
    and its DCG variant, accumulate errors *alongside* disjuncts,
    to be checked just once, at the end, outside the loop. Fix the second
    issue by having parse_goal_disjunction test whether the right operand
    of the semicolon has the form of a disjunction, and if it does,
    recursing on it directly. This makes parse_goal_disjunction
    self-tail-recursive, which should allow it to process disjunctions
    of arbtrary length using fixed stack space (in grades that support
    tail recursion, that is).

    Move the code to flatten disjunctions from goal_expr_to_goal.m to
    these modules, because it is simpler to get the right result this way
    in DCG clauses (for non-DCG clauses, it works simply either way).

compiler/goal_expr_to_goal.m:
    Convert the updated parse tree representation of disjunctions to HLDS,
    and don't flatten disjunctions here anymore.

compiler/parse_item.m:
    Add some infrastructure for debugging changes like this.

compiler/add_clause.m:
    Improve the infrastructure of debugging changes like this, by making it
    more selective.

    To make this possible, pass the predicate name to a predicate
    that did not need it before. Fix the argument order of that predicate.

compiler/make_hlds_warn.m:
    Don't flatten parse tree disjunctions, since the code constructing them
    has done it already.

compiler/get_dependencies.m:
compiler/module_qual.collect_mq_info.m:
compiler/parse_tree_out_clause.m:
compiler/prog_item_stats.m:
compiler/prog_util.m:
    Conform to the change in prog_item.m.

compiler/instance_method_clauses.m:
    Conform to the change in add_clause.m.

tests/hard_coded/flatten_disjunctions.{m,exp}:
    A new test case both testing and documenting the need for flattening
    disjunctions.

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

tests/invalid/require_switch_arms_detism.err_exp:
    Expect updated numbers for anonymous variables. This is due to
    goal_expr_to_goal.m now processing disjuncts in a different order
    than before.
2022-05-06 15:19:49 +10:00
Zoltan Somogyi
e144a91c83 Fix silent failure during module qualification.
This fixes Mantis bug #557.

compiler/module_qual.qualify_items.m:
    When module qualifying checked type, inst and mode definitions,

    - qualify the checked definition as appropriate to the module section
      where the definition's body is, and

    - do not discard any error messages generated by this process in favor of
      the error messages (if any) generated by qualifying the source
      definitions the checked definition was constructed from.

    The source of the Mantis #557 bug was that in a type definition,
    an argument type was (a) uniquely qualifiable in the interface section,
    but (b) was ambiguous in the implementation section, due to an extra
    module import being visible in the implementation section. The first
    change above fixes this bug. The second change is there to ensure that
    if we set the flag that says we found a non-uniquely-module-qualifiable
    type, inst or mode name, the error message we generate when we do that
    won't be discarded. The second change also means that such errors get
    two error messages generated for them, but since we always sort
    error_specs and any remove duplicates, this is not a problem.

tests/hard_coded/bug557.{m,exp}:
tests/hard_coded/bug557_helper.m:
    The test case for this bug, with a comment explaining the bug.

tests/hard_coded/Mmakefile:
    Enable the new test case.
2022-04-11 13:37:41 +10:00
Julien Fischer
0a7365dd95 Add write_binary_utf8_string.
Add predicates for writing the UTF-8 encoding of strings to binary output
streams.

library/io.m:
library/io.primitives_write.m:
    Add the new predicates.

NEWS:
    Announce the additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/write_binary_utf8.{m,exp}:
    Add a test of the new predicates.
2022-04-07 12:29:46 +10:00
Julien Fischer
bc79412af2 Delete the old random number generator.
It has been deprecated since Mercury 20.01.

library/random.m:
    Delete the old generator.

library/array.m:
    Delete the predicate random_permutation/4.

NEWS:
    Announce the above.

tests/hard_coded/string_hash.m:
    Update this test to use the new RNG framework.

tests/hard_coded/Mmakefile:
tests/hard_coded/random_permutation.{m,exp}:
tests/hard_coded/random_simple.{m,exp}:
    Delete these tests, they were specific to the old RNG.

extras/curs/samples/nibbles.m:
extras/solver_types/library/any_array.m:
    Replace use of the old RNG.
2022-03-15 16:08:48 +11:00
Zoltan Somogyi
1db00c99aa Add gap_foldl, last_gap_foldl, chunk_foldl{,2,3,4}.
library/list.m:
    Add the above predicates to the list module.

NEWS:
    Announce the new predicates.

tests/hard_coded/fold_tests.{m,exp}:
    Test case for the new functionality.

tests/hard_coded/Mmakefile:
    Enable the new test case.
2022-03-15 12:18:07 +11:00
Peter Wang
a98151c910 Fix writing of coerce casts in .opt files.
We inadventently wrote out 'coerce' casts in .opt files as:

    V_2 = 'coerce expression'(V_3).

In commit 233874403f, cast_type_to_string
was changed to return "coerce expression" instead of simply "coerce"
for a slight improvement in mode errors.

compiler/hlds_out_goal.m:
    Don't use the result of cast_type_to_string when when writing out
    coerce casts.

tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/coerce_opt.exp:
tests/hard_coded/coerce_opt.m:
tests/hard_coded/coerce_opt_2.m:
    Add test case.
2022-02-16 17:29:20 +11:00
Zoltan Somogyi
9012395ec2 Don't let ml_tag_switch.m generate duplicate fields.
This fixes the second problem identified by Mantis bug #548.

compiler/ml_tag_switch.m:
    Detect the circumstances in which this problem would arise.
    In such cases, simply fail, and let ml_switch_gen.m fall back
    to implementing the switch as an if-then-else chain.

compiler/ml_switch_gen.m:
    Implement that fallback.

compiler/switch_util.m:
    The new code in ml_tag_switch.m needs to thread a fourth piece of state
    through the predicate it passes to group_cases_by_ptag, so change
    its argument list to accommodate such predicates. And since some other
    modules pass the same predicates to group_cases_by_ptag and
    string_binary_cases, make the same change in the argument list
    of that predicate as well.

    Delete one stray comment, and note that another comment seems misplaced.

compiler/ml_string_switch.m:
compiler/string_switch.m:
compiler/switch_case.m:
compiler/tag_switch.m:
    Conform to the changes in switch_util.m.

tests/hard_coded/bug548.exp:
tests/hard_coded/Mmakefile:
    Enable the previously-added test case for Mantis #548, after
    add an .exp file for it.
2022-02-11 21:32:53 +11:00
Julien Fischer
7bcacd13c9 Add casts to and from int32 and int{8,16,64}.
library/int32.m:
     Add the above casts.

NEWS:
     Announce the additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/int32_int{8,16,64}.{m,exp}:
     Add tests of the new functions.
2022-01-14 14:52:05 +11:00
Julien Fischer
5fa7d13b90 Add casts to and from uint32 and uint16.
While these casts can be implemented by casting via uint, the resulting
code is less readable than code that uses direct casts.

library/uint32.m:
    Add cast_from_uint16/1 and cast_to_uint16/1.

NEWS:
    Announce the above additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/uint32_uint16_casts.{m,exp}:
    Add tests for the new casts.
2022-01-03 20:03:31 +11:00
Julien Fischer
ae37bc873c Add a test for array.append.
tests/hard_coded/Mmakefile:
tests/hard_coded/array_append.{m,exp}:
   As above.
2021-11-27 02:50:29 +11:00
Julien Fischer
a3b882930f Add casts to and from uint{16,32,64} and uint8.
While these casts can be implemented by casting via uint, the resulting code is
less readable than code that uses direct casts.

library/uint16.m:
library/uint32.m:
library/uint64.m:
    Add cast_from_uint8/1 and cast_to_uint8/1 to these modules.

NEWS:
    Announce the above additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/uint{16,32,64}_uint_casts.{m,exp}:
    Add tests for the new casts.
2021-11-13 15:09:25 +11:00
Adrian Wong
5e827201f3 Fix a bug where valid code points were treated like invalid surrogates.
runtime/mercury_string.h:
    As above. Valid code points in the ranges [1D800, 1DFFF] and
    [10D800, 10DFFF] were treated like invalid surrogates because the
    high bits were masked away.

tests/hard_coded/Mmakefile:
tests/hard_coded/char_not_surrogate.exp:
tests/hard_coded/char_not_surrogate.m:
tests/hard_coded/string_not_surrogate.exp:
tests/hard_coded/string_not_surrogate.m:
    Add test cases.
2021-11-04 00:46:05 +11:00
Julien Fischer
1cf2eb27ef Add tests of uint8 to decimal string conversion.
tests/hard_coded/uint8_to_string.{m,exp}:
tests/hard_coded/Mmakefile:
    Add the new test.
2021-10-31 19:54:42 +11:00
Julien Fischer
cd75789501 Add tests of uint{16,64} to decimal string conversion.
This is to support upcoming changes to how these conversions are implemented.

tests/hard_coded/uint{16,64}_to_string.{m,exp}:
    Add the new tests.

tests/hard_coded/uint32_to_string.m:
    Adjust a comment.

tests/hard_coded/Mmakefile:
   Add the new tests.
2021-10-31 17:32:32 +11:00
Peter Wang
e6c245092a Fix reverse implication goals.
compiler/parse_goal.m:
    Fix typo: A <= B was parsed as B => B.

tests/hard_coded/Mmakefile:
tests/hard_coded/implication.exp:
tests/hard_coded/implication.m:
    Add test case.

NEWS:
    Announce change.
2021-10-28 10:50:35 +11:00
Julien Fischer
cd540da1f2 Speed up uint32 to string conversion in C grades.
In C grades, uint32_to_string/1 is currently implemented by doing the
following:

 1. Calling sprintf() to write the string into a buffer on the stack.
 2. Calling strlen() on the buffer to determine the actual number of digits.
 3. Allocate the appropriate amount of space on the heap.
 4. Copying the string from the buffer on to the heap.

The benchmark included in this diff contains a number of alternative
implementations, all of which avoid much of the above overhead.
All of these implementations work by computing the required number of digits,
allocating space on the heap and then writing the digits into the string
backwards.

library/string.m:
    Replace uint32_to_string with a faster implementation.
    (This is alternative 1 in the benchmark program below.)

tests/hard_coded/Mmakefile:
tests/hard_coded/uint32_to_string.{m,exp}:
    A test of uint32 to string.

benchmarks/progs/integer_to_string/uint32_conversion.m:
    A program for benchmarking various uint32 to string conversion
    implementations.
2021-10-27 22:28:01 +11:00
Zoltan Somogyi
08de857d26 Don't run hard_coded/setenv in deep prof grades. 2021-07-31 16:55:38 +10:00
Julien Fischer
7bffc574e9 Fix a bug in uint64.cast_from_uint/1.
Add a test of uint -> uint64 conversion.

library/uint64.m:
    Fix a typo that broke uint64.cast_from_uint/1.

tests/hard_coded/Mmakefile:
tests/hard_coded/from_uint_uint64.{m,exp,exp2}:
    Add a test of uint -> uint64 conversion.

tests/hard_coded/from_int_int*.m:
tests/hard_coded/from_uint_uint*.m:
    Fix errors in comments.
2021-07-10 04:44:51 +10:00
Zoltan Somogyi
4926b38ea6 Add uint->uintN conversions.
library/uint16.m:
library/uint32.m:
library/uint64.m:
library/uint8.m:
    Add to each of these modules whichever subset of {from_uint, det_from_uint,
    cast_from_uint} makes sense for that module.

tests/hard_coded/from_uint_uint8.{m,exp}:
tests/hard_coded/from_uint_uint16.{m,exp}:
tests/hard_coded/from_uint_uint32.{m,exp}:
    Three new test cases to test the changes to uint{8,16,32}.m.
    The change to uint64.m will be tested later.

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

library/string.m:
    Add ways to convert strings to uints.

NEWS:
    Announce the new predicates and functions.
2021-06-30 23:55:56 +10:00
Julien Fischer
ee2804ad7d Add a test of int -> uint64 conversion.
tests/hard_coded/Mmakefile:
tests/hard_coded/from_int_uint64.{m,exp*}:
     As above.
2021-06-30 22:58:48 +10:00
Julien Fischer
81651698d8 Add a test of int -> int64 conversion.
tests/hard_coded/Mmakefile:
tests/hard_coded/from_int_int64.{m,exp*}:
     As above.
2021-06-30 22:54:22 +10:00
Julien Fischer
1eb1e5f46e Enable a test case.
tests/hard_coded/Mmakefile:
    Enable the bimap_set_bug test case.  (I neglected to do
    so when I added the test back in 2005.)
2021-06-27 23:56:10 +10:00
Zoltan Somogyi
48e714d43f Make constant prop work with loop invariant opt.
compiler/common.m:
    The code that tries to optimize X = f(...) into X = Y if Y already
    contains f(...) used to insist on the X = f(...) construction unification
    being marked as a dynamic unification, i.e. one that constructs a term
    on the heap on each invocation. This was part of the fix of Mantis bug
    #493, which affected only the MLDS code generator, but for LLDS backend,
    in the presence of --loop-invariants, it prevented a constant propagation
    optimization that we had a test for (tests/hard_coded/constant_prop_2).
    So make both backends happy by insisting on construct_dynamically
    only for the MLDS backend.

compiler/simplify_info.m:
    Record for common.m whether the backend we are targeting pays
    any attention to whether a cell is construct_dynamically.

    Replace some bools with bespoke types, to eliminate the risk of confusion.

compiler/hlds_goal.m:
    For each construction unification marked construct_statically, record
    whether the term was "born static" by being created as a static term
    by a compiler pass, or whether it is a user-written unification that was
    "marked static" by mark_static_terms.m. Document the meaning of both.
    (I originally thought this distinction would be useful in the bug fix,
    but it turned out not to be.)

compiler/deep_profiling.m:
compiler/dep_par_conj.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/polymorphism.m:
compiler/polymorphism_type_info.m:
    Record compiler-generated static terms as born static.

compiler/mark_static_terms.m:
    Mark discovered-to-be-static terms as marked static.

compiler/hlds_out_goal.m:
compiler/interval.m:
compiler/liveness.m:
compiler/loop_inv.m:
compiler/ml_unify_gen_construct.m:
compiler/quantification.m:
compiler/rbmm.add_rbmm_goal_infos.m:
compiler/simplify_goal.m:
compiler/simplify_goal_conj.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_scope.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.versions.m:
compiler/unify_gen_construct.m:
compiler/var_locn.m:
    Conform to the changes above.

tests/hard_coded/constant_prop_loop_inv.{m,exp}:
    A new test case. It contains the part of the constant_prop_2 test case
    that used to fail in LLDS grades with --loop-invariants.

tests/hard_coded/Mercury.options:
    Specify --loop-invariants for the new test case, even if it is not
    specified for constant_prop_2.

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

tests/hard_coded/constant_prop_2.m:
    Fix programming style.
2021-05-13 13:34:07 +10:00
Peter Wang
e9dafb3ec6 Add foreign_proc attributes may_export_body/may_not_export_body.
Add an attribute may_not_export_body to prevent a foreign_proc from
being opt-exported. Also add may_export_body for completeness.

compiler/prog_data_foreign.m:
    Add type to represent those attributes.

    Add a field for that attribute to pragma_foreign_proc_attributes,
    plus getters and setters.

compiler/parse_pragma_foreign.m:
    Parse may_export_body and may_not_export_body attributes on
    foreign_proc declarations.

    Detect conflicting attributes.

compiler/parse_tree_out_pragma.m:
    Write out may_export_body and may_not_export_body attributes.

compiler/intermod.m:
    Do not write a foreign_proc with may_not_export_body to .opt files.

compiler/simplify_proc.m:
    Report an error if a foreign_proc with may_export_body is
    also marked with pragma no_inline.

compiler/add_mutable_aux_preds.m:
    Mark auxiliary predicates for mutables with may_not_export_body
    instead of may_not_duplicate. This allows calls to those predicates
    to be inlined.

doc/reference_manual.texi:
    Document the new attributes.

tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/intermod_may_export_body.exp:
tests/hard_coded/intermod_may_export_body.m:
tests/hard_coded/intermod_may_export_body2.m:
tests/invalid/Mmakefile:
tests/invalid/test_may_export_body.err_exp:
tests/invalid/test_may_export_body.m:
    Add test cases.

vim/syntax/mercury.vim:
    Update vim syntax file.

NEWS:
    Announce addition.
2021-04-20 11:05:29 +10:00
Peter Wang
d1522cbcb2 Make subtypes inherit user-defined equality/comparison from base type.
Since values of a subtype are tested for equality or compared
by first converting to the base type then testing/comparing,
it means that subtypes implicitly inherited any user-defined
equality/comparison from the base type. Allowing a subtype to also
define its own equality/comparison predicates seems more confusing
than useful, so disallow it.

compiler/prog_data.m:
    Add a option noncanon_subtype to maybe_canonical.

compiler/add_type.m:
    Report an error if a subtype defined in the current module
    has user-defined equality or comparison.

    Set the maybe_canonical field of hlds_type_defn for a subtype if the
    if the base type is noncanonical. Setting it to noncanon() makes the
    type_ctor_info have a MR_TypeCtorRep value of
    MR_TYPECTOR_REP_*_USEREQ.

compiler/unify_proc.m:
    Handle subtypes ahead of (other) noncanonical types when generating
    unify or compare proc clauses.

compiler/dead_proc_elim.m:
compiler/hlds_out_module.m:
compiler/intermod.m:
compiler/post_term_analysis.m:
compiler/special_pred.m:
    Conform to changes.

doc/reference_manual.texi:
    Document change.

tests/hard_coded/Mmakefile:
tests/hard_coded/subtype_user_compare.exp:
tests/hard_coded/subtype_user_compare.m:
tests/hard_coded/subtype_user_compare2.m:
tests/invalid/Mercury.options:
tests/invalid/Mmakefile:
tests/invalid/subtype_user_compare.err_exp:
tests/invalid/subtype_user_compare.m:
    Add test cases.
2021-04-13 11:38:15 +10:00
Julien Fischer
a52b094e25 Setting and testing individual bits of uint8s, uint16s and uint64s.
library/uint8.m:
library/uint16.m:
library/uint64.m:
    Add functions for setting, clearing, flipping and testing
    the individual bits of a uint8, uint16 and uint64 values.

NEWS:
    Announce the new functions.

tests/hard_coded/Mmakefile:
tests/hard_coded/bit_access_uint{8,16,64}.{m,exp}:
    Add a test case.
2021-04-10 03:21:14 +10:00
Julien Fischer
e54e47788d Add functions for setting and testing individual bits of uint32s.
library/uint32.m:
    Add functions for setting, clearing, flipping and testing
    the individual bits of a uint32 value.

NEWS:
    Announce the new functions.

tests/hard_coded/Mmakefile:
tests/hard_coded/bit_access_uint32.{m,exp}:
    Add a test case.
2021-04-09 22:37:07 +10:00
Peter Wang
95f59cf7c9 Fix lookup switches on subtype enums.
compiler/switch_util.m:
    Rename dont_need_bit_vec_check variant of need_bit_vec_check to
    dont_need_bit_vec_check_no_gaps.

    Add dont_need_bit_vec_check_with_gaps (see below).

    Make type_range return the correct min and max values used by a
    subtype enum type. For now, it fails unless the range of values
    is contiguous.

    Make find_int_lookup_switch_params use the min and max values for a
    type returned by type_range, not assuming 0 to the max value.

    Make find_int_lookup_switch_params return
    dont_need_bit_vec_check_with_gaps when a bit vector check is not
    required before a table lookup, yet the table is expected to contain
    dummy rows. This is the case for a cannot_fail switch on a subtype
    enum type type, where the subtype does not use some values between
    the min and max values.

compiler/dense_switch.m:
    Make tagged_case_list_is_dense_switch use the min and max values for
    a type returned by type_range, not assuming 0 to the max value.

compiler/ml_lookup_switch.m:
    Expect the generated lookup table to contain dummy rows or not
    depending on dont_need_bit_vec_check_{with_gaps,no_gaps}.

    Conform to change to need_bit_vec_check.

compiler/lookup_switch.m:
compiler/ml_string_switch.m:
    Conform to change to need_bit_vec_check.

tests/hard_coded/Mmakefile:
tests/hard_coded/dense_lookup_switch4.exp:
tests/hard_coded/dense_lookup_switch4.m:
tests/hard_coded/dense_lookup_switch_non2.exp:
tests/hard_coded/dense_lookup_switch_non2.m:
    Add test cases.
2021-04-09 17:41:23 +10:00
Peter Wang
5205908cd3 Make subtypes share standard ordering with base type.
doc/reference_manual.texi:
    Define the standard ordering of a subtype to be the same as that of
    its base type.

    Suggest that subtype constructors should be declared in the same
    order as in the supertype.

compiler/add_type.m:
    Warn if a subtype's constructors are declared in a different
    relative order to the supertype.

compiler/unify_proc.m
    Generate unify/compare procs for subtypes that cast to the base type
    then call the unify/compare proc for the base type. This was
    previously done only for the high-level data representation.

tests/hard_coded/Mmakefile:
tests/hard_coded/subtype_order.exp:
tests/hard_coded/subtype_order.m:
tests/warnings/Mmakefile:
tests/warnings/subtype_order.exp:
tests/warnings/subtype_order.m:
    Add test cases.
2021-04-09 17:41:23 +10:00