Implement type_spec_constrained_preds pragmas.

This pragma, which has the form shown by this example,

    :- pragma type_spec_constrained_preds(
        [stream.line_oriented(Stream, State),
            stream.unboxed_reader(Stream, char, State, Error),
            stream.putback(Stream, char, State, Error)],
        apply_to_superclasses,
        [subst([Stream => io.text_input_stream,
            State => io.state, Error => io.error])]).

allows programmers to ask the compiler to create type-specialized versions
of all predicates and functions, in a module and its submodules, that have
one or more of the specified typeclass constraints.

The first argument specifies these constraints, of which the example above
has three. The second argument specifies whether the request also applies
to predicates and functions whose signatures include superclasses of the
type classes involved (or *their* superclasses, and so on), not the named
type classes themselves. The third argument specifies the requested list
of one or more specializations, each of which consists of a substitution
that maps one or more type variables to a type. (A type that should not
itself be a type variable.) This example requests just one specialization
for each match.

compiler/prog_item.m:
    Add a new kind of decl_pragma item to represent the new pragma.
    Define the new types it needs.

    Add some documentation of the invariants of existing item kinds.

compiler/prog_data.m:
    Define ground_type, a subtype of mer_type, for use by prog_item.m.

compiler/prog_type_test.m:
    Add a utility predicate for converting a type to a ground_type,
    if it is indeed ground.

compiler/prog_data_pragma.m:
    Change the definition of the type_subst type to use a purpose-specific
    function symbol instead of the pair function symbol.

compiler/parse_pragma.m:
    Add code to parse the new pragma, and to check the parsed form
    to see whether it violates the requirements upon it.

    Modify the code that parses plain old type_spec pragma to also allow
    subst([State = io.state, Error = io.error]) syntax to be used
    to specify type substitutions, as discussed on m-rev.

    Modify the code that parses the old substitution syntax to use
    the infrastructure of the new syntax, which can generate better
    error messages.

    Change this now-common code to allow the two sides of a substitution
    to be separated by either an equal sign (such as "State = io.state")
    or an arrow (such as "Error => io.error").

    Improve the wording of some error messages.

    Delete the code that accepted and then ignored a third argument
    in type_spec pragmas. This code was needed only until a change committed
    in July 2022 finished bootstrapping.

vim/syntax/mercury.vim:
    Add the new pragma's name to the list of pragma keywords.

compiler/add_pragma.m:
compiler/add_pragma_type_spec.m:
    Add code to process the new pragma. Add code to debug the processing
    of the new pragma.

    Change the code that processes the old type_spec pragma,

    - to avoid using mode-specific clauses if the specialization applies
      to the whole predicate and not just one procedure of it (this avoids
      a bug that I reported on m-rev on 2024 feb 2), and

    - to set the context of type-specialized predicates to match the original
      predicates, instead of leaving them set to the default context, which
      is a dummy context (this helps avoid error messages whose lack of context
      can make it hard to figure out what exactly they are complaining about).

compiler/options.m:
doc/user_guide.texi:
    Add an option that add_pragma_type_spec.m now consults to decide
    whether to report the type_spec pragmas generated to implement each
    type_spec_constrained_preds pragma. The documentation of this option
    is commented out. It should be made visible to users once we have
    (a) gathered sufficient experience with the new pragma to have confidence
    in it, and (b) documented the pragma itself.

    Add a way to check whether this diff exists in the compiler.

compiler/handle_options.m:
    Automatically disable the new option for all invocations other than
    those that generate code or check errors, since the output they generate
    would be more distracting than useful e.g. when making .intN files.

compiler/parse_class.m:
    Restructure the code that selects superclass constraints (constraints
    on typeclass declarations) out of the whole set of constraints that
    a predicate that is designed to parse constraints on *predicate*
    declarations has parsed. The two use cases are different, because
    neither inst constraints, nor typeclass constraints involving
    partially-specified types, are allowed in typeclass declarations.
    The restructure allows us to improve the error messages we generate
    if and when any such disallowed constraints are found.

compiler/parse_tree_out_pragma.m:
    Add code to output the new pragma.

    Add code to try to avoid putting redundant parentheses around
    name/arity pairs. It needs new code to be enabled in
    parse_tree_out_sym_name.m to work.

compiler/parse_tree_out_type.m:
    Generalize (and rename) an existing function.

compiler/parse_tree_out_sym_name.m:
    Add code (commented out for now) that can avoid putting redundant
    parentheses around name/arity pairs.

compiler/maybe_error.m:
    Define maybeN for N = 6, to join N = {1,2,3,4,5}, for use by new code
    above.

mdbcomp/sym_name.m:
    Fix a misleading predicate name.

compiler/hlds_class.m:
    Document an invariant.

compiler/hlds_module.m:
    Replace a multi_map with a one_or_more_map, and give a name to the type.

compiler/parse_item.m:
    Fix comments.

compiler/parse_tree_out_inst.m:
    Add a new utility function needed by other code in this diff.

compiler/hlds_out_typeclass_table.m:
    Clarify the typeclass table part of HLDS dumps.

compiler/check_import_accessibility.m:
compiler/check_typeclass.m:
compiler/convert_parse_tree.m:
compiler/equiv_type.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
compiler/parse_type_name.m:
compiler/pred_name.m:
compiler/prog_item_stats.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
mdbcomp/slice_and_dice.m:
    Conform to the changes above.

compiler/prog_type_unify.m:
    Fix indentation.

tests/hard_coded/type_spec_modes.m:
    Modify this test to see whether the code parsing type substitutions
    in type_spec pragmas using the new syntax works.

tests/invalid_nodepend/typeclass_test_3.err_exp:
    Expect the improved error message parse_class.m now generates.

tests/invalid_nodepend/bad_tscp.{m,exp}:
    Add this test case to check the error messages generated by parse_pragma.m
    to report the problems it detects in malformed type_spec_constrained_preds
    pragmas.

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

tests/warnings/test_tscp.{m,exp}:
    Add a test case that checks whether, given a list of the new pragmas,
    the compiler generates the expected set of type_spec pragmas.

tests/warnings/{Mmakefile,Mercury.options}:
    Enable the new test case.
This commit is contained in:
Zoltan Somogyi
2024-02-07 16:55:00 +11:00
parent 7dee72cccf
commit d9f5ab5f60
48 changed files with 3095 additions and 335 deletions

View File

@@ -100,6 +100,7 @@ syn keyword mercuryPragma promise_equivalent_clauses
syn keyword mercuryPragma source_file
syn keyword mercuryPragma terminates
syn keyword mercuryPragma type_spec
syn keyword mercuryPragma type_spec_constrained_preds
syn keyword mercuryCInterface foreign_code
syn keyword mercuryCInterface foreign_decl