mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-20 20:03:44 +00:00
We used to parse items (and markers) using a fallback strategy: first we
tried to parse a term as this kind of declaration, then as that kind of marker,
etc, and finally as a clause. This meant that if the term was a malformed
declaration or marker (e.g. because it used the right keyword/functor with
the wrong arity), it could be eventually parsed as a clause.
This diff changes over to a direct parsing strategy: deciding what kind
of item or marker a term SHOULD BE given its top level functor, and
committing to that choice.
There are only two exceptions. The first is that when we see ":- mode",
we keep our mind open about whether this is the definition of a new named mode,
or the declaration of a mode of a predicate or function until we see
a functor one level down.
The second exception is that when we see a purity annotation, a variable
quantification or a constraint at the top level. We used to handle these,
and the "solver" annotation, as "declaration attributes". We started the
processing of every declaration by looking for these attributes, and switching
on the declaration's top functor only if we didn't find them. We now
process their functors in main switch on declarations' functors ("type",
"inst", "pred" etc). Only if one of these switch arms is taken do we go
over into a mode where we gather attributes, and once we have processed
all the attributes in the term, we switch between only the limited set
of declaration types that allow attributes. This avoids having to include
a check for "there were no attributes" in the code that processes all
the *other* kinds of declarations.
Handle the purity annotations separately from the variable quantifications
and the constraints, since while the latter are allowed on both item_pred_decls
and item_mode_decls, the former are allowed only on item_pred_decls.
Handle the solver annotation outside the annotation system altogether,
since it applies only type item_type_defns, and is simple enough
not to need e.g. loops for its processing.
In situations where the top level functor of the term being parsed tells us
that the term SHOULD be an item or marker of a particular kind, but it isn't,
our new approach requires us to generate new error messages.
compiler/prog_io_item.m:
Make the changes described above. By testing the top level of the term
being parsed only once, instead of several times, this should lead to
a very minor speedup. (The main objective of the diff is clarity, not
speed.)
Make the little remaining code dealing with declaration attributes
simpler, replacing multiple traversals with a single traversal.
We used to export parse_decl for prog_io_type_defn to use
to parse method specifications in typeclasses. Replace that
with an exported predicate that is much more closely tailored
for this use case.
Make the predicates that switch on terms' top level functors do
nothing but the switch; put all the code of parsing items or markers
of a given kind into item-or-marker-kind-specific predicates. This
allows us to have two versions of the switch (for "we haven't seen
any attributes" and "we have seen some attributes") without duplicating
any significant amount of code.
Delete the type moved to prog_io_iom.m.
compiler/prog_io_iom.m:
A new module which contains only the definition of the item_or_marker type.
This type used to be private to prog_io_item.m, but some of the other
prog_io_*.m modules can use it to construct values of
maybe1(item_or_marker) directly, instead of constructing just
a maybe1(item) and having prog_io_item.m convert that
maybe1(item_or_marker). The direct method is cleaner
as well as more efficient.
compiler/parse_tree.m:
compiler/notes/compiler_design.html:
Mention the new module.
compiler/prog_io_util.m:
Delete the stuff dealing with decl_attrs, since these have been replaced
with more tightly defined types in prog_io_item.
Make parse_list_of_vars generate useful error messages.
compiler/prog_io.m:
compiler/prog_io_dcg.m:
compiler/prog_io_mode_defn.m:
compiler/prog_io_mutable.m:
compiler/prog_io_pragma.m:
compiler/prog_io_type_defn.m:
compiler/prog_io_typeclass.m:
Take advantage of the above.
Process source_file pragmas in prog_io_pragma.m, not in prog_io_item.m.
In prog_io_type_defn.m, provide a specialized version of a test
for prog_io_pragma.m to use when processing foreign_type pragmas.
In some places, improve error messages.
compiler/recompilation.version.m:
Add a comment.
tests/invalid/bad_initialise_decl.err_exp:
tests/invalid/bigtest.err_exp:
tests/invalid/pragma_source_file.err_exp:
tests/invalid/some.err_exp:
tests/invalid/where_direct_arg2.err_exp:
Expect updated error messages.
16 lines
939 B
Plaintext
16 lines
939 B
Plaintext
bad_initialise_decl.m:015: Error: `i2'/2 used in initialise declaration has
|
|
bad_initialise_decl.m:015: invalid signature.
|
|
bad_initialise_decl.m:015: Error: `:- initialise' declaration in module
|
|
bad_initialise_decl.m:015: interface.
|
|
bad_initialise_decl.m:021: Error: `i1'/2 used in initialise declaration has
|
|
bad_initialise_decl.m:021: invalid signature.
|
|
bad_initialise_decl.m:022: Error: `i3'/2 used in `:- initialise' declaration
|
|
bad_initialise_decl.m:022: does not have a corresponding `:- pred'
|
|
bad_initialise_decl.m:022: declaration.
|
|
bad_initialise_decl.m:023: Error: the predicate specification in an
|
|
bad_initialise_decl.m:023: `:- initialise' declaration must specify the
|
|
bad_initialise_decl.m:023: predicate's arity; `i4' doesn't.
|
|
bad_initialise_decl.m:024: Error: `:- initialise' declaration specifies a
|
|
bad_initialise_decl.m:024: predicate, `(i5 / 6)', whose arity is not zero or
|
|
bad_initialise_decl.m:024: two.
|