mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-17 02:13:54 +00:00
Class and instance definitions both contain lists of methods,
predicates and/or functions, that each have one or more procedures.
Until now, we represented the methods in class and instance definitions
as lists of nothing more than pred_proc_ids. This fact complicated
several operations,
- partly because there was no simple way to tell which procedures
were part of the same predicate or function, and
- partly because the order of the list is important (we identify
each method procedure in our equivalent of vtables with a number,
which is simply the procedure's position in this list), but there was
absolutely no information about recorded about this.
This diff therefore replaces the lists of pred_proc_ids with lists of
method_infos. Each method_info contains
- the method procedure number, i.e. the vtable index,
- the pred_or_func, sym_name and user arity of the predicate or function
that the method procedure is a part of, to make it simple to test
whether two method_infos represent different modes of the same predicate
or function, or not,
- the original pred_proc_id of the method procedure, which never changes,
and
- the current pred_proc_id, which program transformations *can* change.
compiler/hlds_class.m:
Make the change above in the representations of class and instance
definitions.
Put the fields of both types into a better order, by putting
related fields next to each other.
Put a notag wrapper around method procedure numbers to prevent
accidentally mixing them up with plain integers.
Add some utility functions.
compiler/prog_data.m:
Replace three fields containing pred_or_func, sym_name and arity
in the parse tree representation of instance methods with just one,
which contains all three pieces of info. This makes it easier to operate
on them as a unit.
Change the representation of methods defined by clauses from a list
of clauses to a cord of clauses, since this supports constant-time
append.
compiler/hlds_goal.m:
Switch from plain ints to the new notag representation of method
procedure numbers in method call goals.
compiler/add_class.m:
Simplify the code for adding new classes to the HLDS.
Give some predicates better names.
compiler/check_typeclass.m:
Significantly simplify the code for that generates the pred_infos and
proc_infos implementing all the methods of an instances definition,
and construct lists of method_infos instead of lists of pred_proc_ids.
Give some predicates better names.
Some error messages about problems in instance definitions started with
In instance declaration for class/arity:
while others started with
In instance declaration for class(module_a.foo, module_b.bar):
Replace both with
In instance declaration for class(foo, bar):
because it contains more useful information than the first, and less
non-useful information than the second. Improve the wording of some
error messages.
Factor out some common code.
compiler/prog_mode.m:
compiler/prog_type.m:
compiler/prog_util.m:
Generalize the existing predicates for stripping "builtin.m" module
qualifiers from sym_names, cons_ids, insts, types and modes
to allow also the stripping of *all* module qualifiers. This capability
is now used when we print an instance's type vector as a context
for diagnostics about problems inside instance definitions.
compiler/add_pred.m:
Add a mechanism for returning the pred_id of a newly created pred_info,
whether or not it was declared using a predmode declaration. This
capability is now needed by add_class.m.
Move the code creating an error message into its own function, and export
that function for add_class.m.
compiler/polymorphism_type_info.m:
Fix some comment rot.
compiler/base_typeclass_info.m:
compiler/call_gen.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/direct_arg_in_out.m:
compiler/error_msg_inst.m:
compiler/float_regs.m:
compiler/get_dependencies.m:
compiler/higher_order.m:
compiler/hlds_error_util.m:
compiler/hlds_out_goal.m:
compiler/hlds_out_typeclass_table.m:
compiler/instance_method_clauses.m:
compiler/intermod.m:
compiler/make_hlds_error.m:
compiler/ml_call_gen.m:
compiler/mode_errors.m:
compiler/modes.m:
compiler/module_qual.qualify_items.m:
compiler/old_type_constraints.m:
compiler/parse_class.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_inst.m:
compiler/polymorphism_post_copy.m:
compiler/polymorphism_type_class_info.m:
compiler/prog_item.m:
compiler/prog_rep.m:
compiler/recompilation.usage.m:
compiler/state_var.m:
compiler/type_class_info.m:
compiler/typecheck_debug.m:
compiler/typecheck_error_type_assign.m:
compiler/typecheck_errors.m:
compiler/typecheck_msgs.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
Conform to the changes above.
tests/invalid/bug476.err_exp:
tests/invalid/tc_err1.err_exp:
tests/invalid/tc_err2.err_exp:
tests/invalid/typeclass_bogus_method.err_exp:
tests/invalid/typeclass_missing_mode.err_exp:
tests/invalid/typeclass_missing_mode_2.err_exp:
tests/invalid/typeclass_mode.err_exp:
tests/invalid/typeclass_mode_2.err_exp:
tests/invalid/typeclass_mode_3.err_exp:
tests/invalid/typeclass_mode_4.err_exp:
tests/invalid/typeclass_test_10.err_exp:
tests/invalid/typeclass_test_3.err_exp:
tests/invalid/typeclass_test_4.err_exp:
tests/invalid/typeclass_test_5.err_exp:
tests/invalid/typeclass_test_9.err_exp:
Expect the updated wording of some error messages.
182 lines
7.8 KiB
Mathematica
182 lines
7.8 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2022 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% This module produces definitions for the predicates that implement
|
|
% instance methods.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module hlds.make_hlds.instance_method_clauses.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_clauses.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.make_hlds.qual_info.
|
|
:- import_module hlds.status.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module list.
|
|
:- import_module term.
|
|
|
|
% Given the instance_proc_def for a predicate or function from an instance
|
|
% declaration, produce the clauses_info for that instance_proc_def.
|
|
%
|
|
:- pred produce_instance_method_clauses(instance_proc_def::in,
|
|
pred_or_func::in, list(mer_type)::in, pred_markers::in, term.context::in,
|
|
instance_status::in, clauses_info::out, tvarset::in, tvarset::out,
|
|
module_info::in, module_info::out, qual_info::in, qual_info::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.hlds_args.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module hlds.instmap.
|
|
:- import_module hlds.make_hlds.add_clause.
|
|
:- import_module hlds.make_hlds.make_hlds_warn.
|
|
:- import_module hlds.make_hlds.state_var.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.maybe_error.
|
|
:- import_module parse_tree.prog_item.
|
|
:- import_module parse_tree.prog_util.
|
|
:- import_module parse_tree.set_of_var.
|
|
:- import_module parse_tree.var_table.
|
|
:- import_module parse_tree.vartypes.
|
|
|
|
:- import_module cord.
|
|
:- import_module map.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module varset.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
produce_instance_method_clauses(InstanceProcDefn, PredOrFunc, ArgTypes,
|
|
Markers, Context, InstanceStatus, ClausesInfo,
|
|
!TVarSet, !ModuleInfo, !QualInfo, !Specs) :-
|
|
PredFormArity = arg_list_arity(ArgTypes),
|
|
(
|
|
% Handle the `pred(<MethodName>/<Arity>) is <ImplName>' syntax.
|
|
InstanceProcDefn = instance_proc_def_name(InstancePredName),
|
|
% Add the body of the introduced pred.
|
|
% First the goal info, ...
|
|
PredFormArity = pred_form_arity(PredFormArityInt),
|
|
varset.init(VarSet0),
|
|
make_n_fresh_vars("HeadVar__", PredFormArityInt, HeadVars,
|
|
VarSet0, VarSet),
|
|
set_of_var.list_to_set(HeadVars, NonLocals),
|
|
( if check_marker(Markers, marker_is_impure) then
|
|
Purity = purity_impure
|
|
else if check_marker(Markers, marker_is_semipure) then
|
|
Purity = purity_semipure
|
|
else
|
|
Purity = purity_pure
|
|
),
|
|
instmap_delta_init_unreachable(DummyInstMapDelta),
|
|
DummyDetism = detism_erroneous,
|
|
goal_info_init(NonLocals, DummyInstMapDelta, DummyDetism, Purity,
|
|
Context, GoalInfo),
|
|
% ... and then the goal itself.
|
|
construct_and_record_pred_or_func_call(invalid_pred_id, PredOrFunc,
|
|
InstancePredName, HeadVars, GoalInfo, IntroducedGoal, !QualInfo),
|
|
IntroducedClause = clause(all_modes, IntroducedGoal, impl_lang_mercury,
|
|
Context, []),
|
|
|
|
vartypes_from_corresponding_lists(HeadVars, ArgTypes,
|
|
ExplicitVarTypes),
|
|
init_var_table(VarTable),
|
|
rtti_varmaps_init(RttiVarMaps),
|
|
map.init(TVarNameMap),
|
|
HeadVarVec = proc_arg_vector_init(PredOrFunc, HeadVars),
|
|
set_clause_list([IntroducedClause], ClausesRep),
|
|
ClausesInfo = clauses_info(VarSet, ExplicitVarTypes,
|
|
VarTable, RttiVarMaps, TVarNameMap, HeadVarVec, ClausesRep,
|
|
init_clause_item_numbers_comp_gen,
|
|
no_foreign_lang_clauses, no_clause_syntax_errors)
|
|
;
|
|
% Handle the arbitrary clauses syntax.
|
|
InstanceProcDefn = instance_proc_def_clauses(InstanceClausesCord),
|
|
InstanceClauses = cord.list(InstanceClausesCord),
|
|
% XXX CIT_TYPES: should be cit_types(ArgTypes)
|
|
clauses_info_init(PredOrFunc, cit_no_types(PredFormArity),
|
|
init_clause_item_numbers_comp_gen, ClausesInfo0),
|
|
list.foldl5(
|
|
produce_instance_method_clause(PredOrFunc, Context,
|
|
InstanceStatus),
|
|
InstanceClauses, !TVarSet, !ModuleInfo, !QualInfo,
|
|
ClausesInfo0, ClausesInfo, !Specs)
|
|
).
|
|
|
|
:- pred produce_instance_method_clause(pred_or_func::in,
|
|
prog_context::in, instance_status::in, item_clause_info::in,
|
|
tvarset::in, tvarset::out, module_info::in, module_info::out,
|
|
qual_info::in, qual_info::out, clauses_info::in, clauses_info::out,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
produce_instance_method_clause(PredOrFunc, Context, InstanceStatus,
|
|
InstanceClause, TVarSet0, TVarSet, !ModuleInfo, !QualInfo,
|
|
!ClausesInfo, !Specs) :-
|
|
InstanceClause = item_clause_info(ClausePredOrFunc, PredSymName,
|
|
HeadTerms0, ClauseVarSet, MaybeBodyGoal, _ClauseContext, _SeqNum),
|
|
% XXX Can this ever fail? If yes, we should generate an error message
|
|
% instead of aborting.
|
|
expect(unify(PredOrFunc, ClausePredOrFunc), $pred, "PredOrFunc mismatch"),
|
|
( if
|
|
illegal_state_var_func_result(PredOrFunc, HeadTerms0, StateVar,
|
|
StateVarContext)
|
|
then
|
|
TVarSet = TVarSet0,
|
|
report_illegal_func_svar_result(StateVarContext, ClauseVarSet,
|
|
StateVar, !Specs),
|
|
!:Specs = get_any_errors_warnings2(MaybeBodyGoal) ++ !.Specs
|
|
else
|
|
(
|
|
MaybeBodyGoal = error2(BodyGoalSpecs),
|
|
TVarSet = TVarSet0,
|
|
!:Specs = BodyGoalSpecs ++ !.Specs
|
|
;
|
|
MaybeBodyGoal = ok2(BodyGoal, BodyGoalWarningSpecs),
|
|
!:Specs = BodyGoalWarningSpecs ++ !.Specs,
|
|
expand_bang_state_pairs_in_terms(HeadTerms0, HeadTerms),
|
|
% AllProcIds is only used when the predicate has foreign procs,
|
|
% which the instance method pred should not have, so this
|
|
% dummy value should be ok.
|
|
AllProcIds = [],
|
|
% XXX STATUS
|
|
InstanceStatus = instance_status(OldImportStatus),
|
|
PredStatus = pred_status(OldImportStatus),
|
|
clauses_info_add_clause(all_modes, AllProcIds, PredStatus,
|
|
clause_not_for_promise, PredOrFunc, PredSymName, HeadTerms,
|
|
Context, item_no_seq_num, Warnings,
|
|
BodyGoal, Goal, ClauseVarSet, VarSet, TVarSet0, TVarSet,
|
|
!ClausesInfo, !ModuleInfo, !QualInfo, !Specs),
|
|
|
|
PredFormArity = arg_list_arity(HeadTerms),
|
|
PFSymNameArity = pf_sym_name_arity(PredOrFunc, PredSymName,
|
|
PredFormArity),
|
|
% Warn about singleton variables.
|
|
warn_singletons(!.ModuleInfo, PFSymNameArity, VarSet, Goal,
|
|
!Specs),
|
|
% Warn about variables with overlapping scopes.
|
|
add_quant_warnings(PFSymNameArity, VarSet, Warnings, !Specs)
|
|
)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module hlds.make_hlds.instance_method_clauses.
|
|
%-----------------------------------------------------------------------------%
|