mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
Pragmas that apply to a pred_info have traditionally specified that
pred_info by a symname/arity pair. However, this can be ambiguous
if there is both a predicate and a function with that symname/arity pair.
This diff therefore allows pragmas that previously took "symname/arity"
to also take "pred(symname/arity)" and "func(symname/arity").
If e.g. there is both a pred foo/2 and a func foo/2 accessible from
the current module, the old form applied to both, while the new forms
apply to just one.
Later, we could change the behavior of the old form to insist on a
unique match, but before we do, we should have a mechanism that allows
programmers to resolve the ambiguity. (They could rename either the
pred or the func, but it is less intrusive for the compiler not to
insist on that.) This is that mechanism.
In the process of implementing this change, I had to update lots of code
that dealt with arities, since one main difference between predicates
and functions is that for the latter, the user visible arity and
the internal compiler arity are different, in that the former does not
count the return value, and the latter does. The existing "arity" type
is an equivalence to int, and thus does not indicate which notion is meant.
I therefore added two notag types, user_arity and pred_form_arity,
for the two notions above respectively, and made a start on using them,
though for now, only in the code sections affected by the main change above.
compiler/prog_item.m:
Change the types that represent the specifications of predicates
(in the sense of pred_infos) and functions to allow the representation
of not just "symname/arity," but also "pred(symname/arity)" and
"func(symname/arity"). There is one exception: for the oisu (order
independent state update) pragma, require the presence of either
a pred() vs func() wrapper. This is not a breaking change, since oisu
pragmas are neither publicly documented or really implemented.
Pragmas that allow the representation of argument modes implicitly
specify pred vs func by taking the mode list either as
(m1, m2, ... mn) or as (m1, m2, ...) = mn. Encode this invariant
in the representation type. Make this type also include an arity
only in the absence of a mode list, to make unrepresentable
any inconsistent state in which the stated arity and the length
of the mode list disagree.
Give the new types used for these updated representations names
that state whether they specify a pred_info or a proc_info
(or in one case that we should later fix, that they can specify either).
Put the pred or func indication before the symname and arity
both in these new types, and in some old types. Do this both because
the pred or func indication comes before the name in Mercury declarations,
and to help the compiler find all the places where code using the old
forms had to be revisited and checked for any needed updates.
Provide utility operations on the new types involved in the
updated representations.
compiler/prog_data.m:
Add the user_arity and pred_form_arity types, as mentioned above.
Add a type that is mostly used in item representations, but is also
useful elsewhere.
compiler/parse_pragma.m:
compiler/parse_pragma_analysis.m:
compiler/parse_pragma_foreign.m:
compiler/parse_pragma_tabling.m:
compiler/parse_util.m:
Accept the pred() or func() wrappers mentioned above, and generate
the updated representations when parsing terms containing pragmas.
compiler/parse_tree_out_pragma.m:
Accept the updated representations of pragmas when printing them out.
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
Use the updated representations when adding pragmas to the HLDS.
compiler/error_util.m:
Provide mechanisms for use above when printing references to pred_infos
using user arities, to complement the existing mechanisms which use
arities that they treat as pred form arities. The latter is what
you want when generating error messages about pred_infos that
already included functions' return types in the argument list;
the former is what you want when generating error messages
about user input that has not yet been subject to that treatment,
such as a pragma that has just been read in. (The difference is
only in what form of arity these mechanisms take as *input*;
the output is always user arity, which after all is what users
are interested in.)
compiler/hlds_error_util.m:
Provide a user_arity equivalent to a piece of existing pred_form_arity
functionality, for use by the modules above.
Provide utility functions used when generating error messages.
compiler/fact_table.m:
Replace most uses of the "arity" type with the "user_arity" type.
Done mostly in the process of figuring out which kind of arity
the top predicates took as arguments.
Put argument lists into a sensible order.
compiler/prog_out.m:
compiler/prog_util.m:
Add utility functionality needed above.
compiler/add_mutable_aux_preds.m:
compiler/convert_parse_tree.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/module_qual.qualify_items.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/typecheck_errors.m:
compiler/unused_args.m:
Conform to the changes above.
compiler/hlds_pred.m:
Add an XXX.
compiler/notes/order_indep_state_update:
Fix typos.
tests/hard_coded/bad_direct_reuse.m:
tests/hard_coded/bad_indirect_reuse.m:
tests/hard_coded/bitmap_simple.m:
tests/hard_coded/constraint_order.m:
tests/hard_coded/equality_pred_which_requires_boxing.m:
tests/hard_coded/fact_table_test_1.m:
tests/hard_coded/float_consistency.m:
tests/hard_coded/foreign_enum_rtti.m:
tests/hard_coded/foreign_enum_switch.m:
tests/hard_coded/foreign_import_module_2.m:
tests/hard_coded/gh72.m:
tests/hard_coded/gh72a.m:
tests/hard_coded/heap_ref_mask_tag.m:
tests/hard_coded/intermod_multimode.m:
tests/hard_coded/mode_check_clauses.m:
tests/hard_coded/multimode_addr.m:
tests/hard_coded/type_spec_ho_term.m:
tests/hard_coded/user_defined_equality2.m:
Add pred() or func() wrappers to symname/arity pairs in pragmas,
to test whether the parser accepts them.
Fix deviations from our current coding standards.
tests/hard_coded/oisu_check_db.m:
tests/invalid/oisu_check_add_pragma_errors.{m,err_exp}:
tests/invalid/oisu_check_semantic_errors.m:
Add the pred() wrappers now required in oisu pragmas.
Expect the improved wording of an error message.
105 lines
2.2 KiB
Mathematica
105 lines
2.2 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module oisu_check_add_pragma_errors.
|
|
:- interface.
|
|
|
|
:- type foo.
|
|
:- type baz.
|
|
|
|
:- pragma oisu(foo/0,
|
|
creators([pred(create_foo/1)]),
|
|
mutators([pred(mutate_foo/3)])
|
|
).
|
|
|
|
:- pragma oisu(foo/0,
|
|
creators([pred(create_foo/1)]),
|
|
mutators([pred(mutate_foo/3)]),
|
|
destructors([pred(destroy_foo/3)])
|
|
).
|
|
|
|
:- pragma oisu(quux/0,
|
|
creators([pred(create_quux/1)]),
|
|
mutators([pred(mutate_quux/3)]),
|
|
destructors([pred(destroy_quux/2)])
|
|
).
|
|
|
|
:- implementation.
|
|
|
|
:- pragma oisu(bar/0,
|
|
creators([pred(create_bar/1)]),
|
|
mutators([pred(mutate_bar/3)]),
|
|
destructors([pred(destroy_bar/3)])
|
|
).
|
|
|
|
:- pragma oisu(baz/0,
|
|
creators([pred(create_baz/1)]),
|
|
mutators([pred(mutate_baz/3)])
|
|
).
|
|
|
|
:- type foo
|
|
---> foo(int, int).
|
|
|
|
:- type bar
|
|
---> bar(int).
|
|
|
|
:- type baz
|
|
---> baz(float).
|
|
|
|
:- pred create_foo(foo::out) is det.
|
|
:- pred mutate_foo(int::in, foo::in, foo::out) is det.
|
|
:- pred destroy_foo(foo::in, int::out, int::out) is det.
|
|
|
|
create_foo(Foo) :-
|
|
Foo = foo(0, 0).
|
|
|
|
mutate_foo(N, Foo0, Foo) :-
|
|
Foo0 = foo(_, _),
|
|
Foo = foo(N, N).
|
|
|
|
destroy_foo(Foo, A, B) :-
|
|
Foo = foo(A, B).
|
|
|
|
:- pred create_bar(bar::out) is det.
|
|
:- pred mutate_bar(int::in, bar::in, bar::out) is det.
|
|
:- pred destroy_bar(bar::in, int::out) is det.
|
|
|
|
create_bar(Bar) :-
|
|
Bar = bar(0).
|
|
|
|
mutate_bar(N, Bar0, Bar) :-
|
|
Bar0 = bar(_),
|
|
Bar = bar(N).
|
|
|
|
destroy_bar(Bar, A) :-
|
|
Bar = bar(A).
|
|
|
|
:- pred create_baz(baz::out) is det.
|
|
:- pred mutate_baz(float::in, baz::in, baz::out) is det.
|
|
:- pred destroy_baz(baz::in, float::out) is det.
|
|
|
|
create_baz(Baz) :-
|
|
Baz = baz(0).
|
|
|
|
mutate_baz(N, Baz0, Baz) :-
|
|
Baz0 = baz(_),
|
|
Baz = baz(N).
|
|
|
|
destroy_baz(Baz, A) :-
|
|
Baz = baz(A).
|
|
|
|
:- pred create_quux(baz::out) is det.
|
|
:- pred mutate_quux(float::in, baz::in, baz::out) is det.
|
|
:- pred destroy_quux(baz::in, float::out) is det.
|
|
|
|
create_quux(Baz) :-
|
|
Baz = baz(0).
|
|
|
|
mutate_quux(N, Baz0, Baz) :-
|
|
Baz0 = baz(_),
|
|
Baz = baz(N).
|
|
|
|
destroy_quux(Baz, A) :-
|
|
Baz = baz(A).
|