Files
mercury/compiler/instance_method_clauses.m
Zoltan Somogyi 18817d62d0 Record more than a pred_proc_id for each method.
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.
2022-11-22 02:27:33 +11:00

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.
%-----------------------------------------------------------------------------%