mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
We haven't supported it in years, and keeping it in the compiler
is just a maintenance burden and a performance problem.
mdbcomp/prim_data.m:
Delete the spec_pred_init functor, since we don't support special
"init" predicates anymore.
compiler/prog_data.m:
Delete the slot in solver type details that record the name of the
auto-initialization predicate.
compiler/prog_io_type_defn.m:
Don't allow a type definition to specify an auto-initialization predicate.
compiler/options.m:
compiler/globals.m:
Delete the option that allowed support for auto-initialization to be
turned back on.
compiler/inst_match.m:
compiler/inst_util.m:
Delete comments about auto-initialization.
compiler/mode_info.m:
Delete the record of whether we have variables that can be
auto-initialized (we never do anymore) and the flag that controls whether
auto-initialization is permitted or not.
compiler/modecheck_conj.m:
Simplify the code that modechecks conjunctions, since it no longer
has to figure out where to insert auto-initializations of solver vars.
compiler/modecheck_goal.m:
Delete the code that ensured that if one branch of a branched
control structure auto-initialized a solver variable, then they
all did.
compiler/modecheck_unify.m:
Don't auto-initializate variables before unifications.
compiler/modecheck_util.m:
Delete the code that auto-initialized solver variables at the ends
of procedure bodies if this needed to be done and wasn't done before.
compiler/add_special_pred.m:
compiler/equiv_type.m:
compiler/equiv_type_hlds.m:
compiler/get_dependencies.m:
compiler/hlds_module.m:
compiler/hlds_pred.m:
compiler/modecheck_call.m:
compiler/modes.m:
compiler/module_qual.qualify_items.m:
compiler/parse_tree_out.m:
compiler/post_term_analysis.m:
compiler/smm_common.m:
compiler/special_pred.m:
compiler/term_constr_errors.m:
compiler/term_constr_initial.m:
compiler/term_util.m:
compiler/termination.m:
compiler/trace_params.m:
compiler/type_util.m:
compiler/unify_proc.m:
Delete code that handled stuff related to auto-initialization,
and now always take the path that would normally be taken in the
absence of auto-initialization.
deep_profiler/read_profile.m:
runtime/mercury_layout_util.c:
runtime/mercury_stack_trace.c:
util/mdemangle.c:
Remove code that recognized the compiler-generated name of initialization
predicates.
tests/debugger/solver_test.m:
tests/hard_coded/solver_construction_init_test.m:
tests/hard_coded/solver_disj_inits.m:
tests/hard_coded/solver_ite_inits.m:
tests/invalid/missing_init_pred.m:
tests/invalid/zinc2mer_lib.m:
tests/valid/fz_conf.m:
tests/valid/solver_type_bug_2.m:
tests/valid/solver_type_mutable_bug.m:
These tests tested the handling of auto-initialization, which we
no longer support. Keep them around (and a bit more visible than
inside the git repo) in case we need them again, but add a comment
to each saying that the test is disabled.
tests/debugger/Mercury.options:
tests/debugger/Mmakefile:
tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/invalid/Mercury.options:
tests/invalid/Mmakefile:
tests/valid/Mercury.options:
tests/valid/Mmakefile:
Disable those tests.
tests/warnings/non_term_user_special.{m,exp}:
Part of this test tested the handling of auto-initialization;
delete that part.
tests/warnings/Mercury.options:
Delete the flag required by the deleted part, since we don't support it
anymore.
368 lines
14 KiB
Mathematica
368 lines
14 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-2000,2002-2011 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: special_pred.m.
|
|
% Main author: fjh.
|
|
%
|
|
% Certain predicates are implicitly defined for every type by the compiler.
|
|
% This module defines most of the characteristics of those predicates.
|
|
% (The actual code for these predicates is generated in unify_proc.m.)
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module hlds.special_pred.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_data.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.status.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module list.
|
|
:- import_module map.
|
|
|
|
:- type special_pred_maps
|
|
---> special_pred_maps(
|
|
spm_unify_map :: map(type_ctor, pred_id),
|
|
spm_index_map :: map(type_ctor, pred_id),
|
|
spm_compare_map :: map(type_ctor, pred_id)
|
|
).
|
|
|
|
:- pred search_special_pred_maps(special_pred_maps::in,
|
|
special_pred_id::in, type_ctor::in, pred_id::out) is semidet.
|
|
:- pred lookup_special_pred_maps(special_pred_maps::in,
|
|
special_pred_id::in, type_ctor::in, pred_id::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred special_pred_list(list(special_pred_id)::out) is det.
|
|
|
|
:- pred special_pred_description(special_pred_id::in, string::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Return the predicate name we should use for the given special_pred
|
|
% for the given type constructor.
|
|
%
|
|
:- func special_pred_name(special_pred_id, type_ctor) = string.
|
|
|
|
:- pred special_pred_mode_num(special_pred_id::in, int::out) is det.
|
|
|
|
% This predicate always returns determinism `semidet' for unification
|
|
% procedures. For types with only one value, the unification is actually
|
|
% `det', however we need to pretend it is `semidet' so that it can be
|
|
% called correctly from the polymorphic `unify' procedure.
|
|
%
|
|
:- pred special_pred_interface(special_pred_id::in, mer_type::in,
|
|
list(mer_type)::out, list(mer_mode)::out, determinism::out) is det.
|
|
|
|
% Given a special pred id and the list of its arguments, work out which
|
|
% argument specifies the type that this special predicate is for. Note that
|
|
% this gets called after the polymorphism.m pass, so type_info arguments
|
|
% may have been inserted at the start; hence we find the type at a known
|
|
% position from the end of the list (by using list.reverse).
|
|
%
|
|
% Currently for most of the special predicates the type variable can be
|
|
% found in the last type argument, except for index, for which it is the
|
|
% second-last argument.
|
|
%
|
|
:- pred special_pred_get_type(special_pred_id::in, list(prog_var)::in,
|
|
prog_var::out) is semidet.
|
|
|
|
:- pred special_pred_get_type_det(special_pred_id::in, list(prog_var)::in,
|
|
prog_var::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Succeeds if the declarations and clauses for the special predicates
|
|
% for the given type generated only when required. This will succeed
|
|
% for imported types for which the special predicates do not need
|
|
% typechecking.
|
|
%
|
|
:- pred special_pred_is_generated_lazily(module_info::in, type_ctor::in)
|
|
is semidet.
|
|
|
|
% XXX Document me, and the relationship to the /2 pred just above.
|
|
%
|
|
:- pred special_pred_is_generated_lazily(module_info::in, type_ctor::in,
|
|
hlds_type_body::in, type_status::in) is semidet.
|
|
|
|
% A compiler-generated predicate only needs type checking if
|
|
% (a) it is a user-defined equality pred, or
|
|
% (b) it is the unification or comparison predicate for an existentially
|
|
% quantified type, or
|
|
% (c) it is the initialisation predicate for a solver type.
|
|
%
|
|
:- pred special_pred_for_type_needs_typecheck(module_info::in,
|
|
special_pred_id::in, hlds_type_body::in) is semidet.
|
|
|
|
% Succeed if the type can have clauses generated for its special
|
|
% predicates. This will fail for abstract types and types for which
|
|
% the RTTI information is defined by hand.
|
|
%
|
|
:- pred can_generate_special_pred_clauses_for_type(module_info::in,
|
|
type_ctor::in, hlds_type_body::in) is semidet.
|
|
|
|
% Is this a builtin type whose special predicates are defined in Mercury?
|
|
% If yes, return the name of the type.type
|
|
%
|
|
:- pred is_builtin_type_special_preds_defined_in_mercury(type_ctor::in,
|
|
string::out) is semidet.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Does the compiler generate the RTTI for the builtin types, or is it
|
|
% hand-coded?
|
|
%
|
|
:- pred compiler_generated_rtti_for_builtins(module_info::in) is semidet.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.
|
|
:- import_module check_hlds.type_util.
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.options.
|
|
:- import_module mdbcomp.builtin_modules.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.builtin_lib_types.
|
|
:- import_module parse_tree.prog_mode.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module bool.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
search_special_pred_maps(SpecMaps, SpecialPredId, TypeCtor, PredId) :-
|
|
select_special_pred_map(SpecMaps, SpecialPredId, SpecMap),
|
|
map.search(SpecMap, TypeCtor, PredId).
|
|
|
|
lookup_special_pred_maps(SpecMaps, SpecialPredId, TypeCtor, PredId) :-
|
|
select_special_pred_map(SpecMaps, SpecialPredId, SpecMap),
|
|
map.lookup(SpecMap, TypeCtor, PredId).
|
|
|
|
:- pred select_special_pred_map(special_pred_maps::in,
|
|
special_pred_id::in, map(type_ctor, pred_id)::out) is det.
|
|
|
|
select_special_pred_map(SpecMaps, SpecialPredId, SpecMap) :-
|
|
(
|
|
SpecialPredId = spec_pred_unify,
|
|
SpecMap = SpecMaps ^ spm_unify_map
|
|
;
|
|
SpecialPredId = spec_pred_index,
|
|
SpecMap = SpecMaps ^ spm_index_map
|
|
;
|
|
SpecialPredId = spec_pred_compare,
|
|
SpecMap = SpecMaps ^ spm_compare_map
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
special_pred_list([spec_pred_unify, spec_pred_index, spec_pred_compare]).
|
|
|
|
special_pred_description(spec_pred_unify, "unification predicate").
|
|
special_pred_description(spec_pred_compare, "comparison predicate").
|
|
special_pred_description(spec_pred_index, "indexing predicate").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
special_pred_name(SpecialPred, type_ctor(SymName, Arity)) = Name :-
|
|
BaseName = get_special_pred_id_target_name(SpecialPred),
|
|
AppendTypeId = spec_pred_name_append_type_id,
|
|
(
|
|
AppendTypeId = yes,
|
|
Name = BaseName ++ sym_name_to_string(SymName)
|
|
++ "/" ++ int_to_string(Arity)
|
|
;
|
|
AppendTypeId = no,
|
|
Name = BaseName
|
|
).
|
|
|
|
:- func spec_pred_name_append_type_id = bool.
|
|
:- pragma inline(spec_pred_name_append_type_id/0).
|
|
|
|
% XXX The name demanglers don't yet understand predicate names for special
|
|
% preds that have the type name and arity appended, and the hand-written
|
|
% unify/compare predicates for builtin types such as typeinfo have the plain
|
|
% base names. Therefore returning "yes" here is useful only for debugging
|
|
% the compiler.
|
|
spec_pred_name_append_type_id = no.
|
|
|
|
special_pred_mode_num(_, 0).
|
|
% Mode num for special procs is always 0 (the first mode).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
special_pred_interface(SpecialPredId, Type, ArgTypes, ArgModes, Detism) :-
|
|
(
|
|
SpecialPredId = spec_pred_unify,
|
|
ArgTypes = [Type, Type],
|
|
in_mode(In),
|
|
ArgModes = [In, In],
|
|
Detism = detism_semi
|
|
;
|
|
SpecialPredId = spec_pred_index,
|
|
ArgTypes = [Type, int_type],
|
|
in_mode(In),
|
|
out_mode(Out),
|
|
ArgModes = [In, Out],
|
|
Detism = detism_det
|
|
;
|
|
SpecialPredId = spec_pred_compare,
|
|
ArgTypes = [comparison_result_type, Type, Type],
|
|
in_mode(In),
|
|
uo_mode(Uo),
|
|
ArgModes = [Uo, In, In],
|
|
Detism = detism_det
|
|
).
|
|
|
|
special_pred_get_type(spec_pred_unify, Types, T) :-
|
|
list.reverse(Types, [T | _]).
|
|
special_pred_get_type(spec_pred_index, Types, T) :-
|
|
list.reverse(Types, [_, T | _]).
|
|
special_pred_get_type(spec_pred_compare, Types, T) :-
|
|
list.reverse(Types, [T | _]).
|
|
|
|
special_pred_get_type_det(SpecialId, ArgTypes, Type) :-
|
|
( if special_pred_get_type(SpecialId, ArgTypes, TypePrime) then
|
|
Type = TypePrime
|
|
else
|
|
unexpected($module, $pred, "special_pred_get_type failed")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
special_pred_is_generated_lazily(ModuleInfo, TypeCtor) :-
|
|
CtorCat = classify_type_ctor(ModuleInfo, TypeCtor),
|
|
(
|
|
CtorCat = ctor_cat_tuple
|
|
;
|
|
( CtorCat = ctor_cat_user(_)
|
|
; CtorCat = ctor_cat_enum(_)
|
|
; is_introduced_type_info_type_category(CtorCat) = yes
|
|
),
|
|
module_info_get_type_table(ModuleInfo, TypeTable),
|
|
search_type_ctor_defn(TypeTable, TypeCtor, TypeDefn),
|
|
hlds_data.get_type_defn_body(TypeDefn, TypeBody),
|
|
hlds_data.get_type_defn_status(TypeDefn, TypeStatus),
|
|
special_pred_is_generated_lazily_2(ModuleInfo, TypeBody, TypeStatus)
|
|
).
|
|
|
|
special_pred_is_generated_lazily(ModuleInfo, TypeCtor, TypeBody, TypeStatus) :-
|
|
% We don't want special preds for solver types to be generated lazily
|
|
% because we have to insert calls to their initialisation preds during
|
|
% mode analysis and we therefore require the appropriate names to
|
|
% appear in the symbol table.
|
|
|
|
TypeBody \= hlds_solver_type(_, _),
|
|
TypeBody \= hlds_abstract_type(abstract_solver_type),
|
|
|
|
CtorCat = classify_type_ctor(ModuleInfo, TypeCtor),
|
|
(
|
|
CtorCat = ctor_cat_tuple
|
|
;
|
|
( CtorCat = ctor_cat_user(_)
|
|
; CtorCat = ctor_cat_enum(_)
|
|
; is_introduced_type_info_type_category(CtorCat) = yes
|
|
),
|
|
special_pred_is_generated_lazily_2(ModuleInfo, TypeBody, TypeStatus)
|
|
).
|
|
|
|
:- pred special_pred_is_generated_lazily_2(module_info::in,
|
|
hlds_type_body::in, type_status::in) is semidet.
|
|
|
|
special_pred_is_generated_lazily_2(ModuleInfo, TypeBody, TypeStatus) :-
|
|
(
|
|
type_status_defined_in_this_module(TypeStatus) = no
|
|
;
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
globals.lookup_bool_option(Globals, special_preds, no)
|
|
),
|
|
|
|
% We can't generate clauses for unification predicates for foreign types
|
|
% lazily because they call the polymorphic procedure
|
|
% private_builtin.nyi_foreign_type_unify.
|
|
% polymorphism.process_generated_pred can't handle calls to polymorphic
|
|
% procedures after the initial polymorphism pass.
|
|
TypeBody \= hlds_foreign_type(_),
|
|
|
|
% The special predicates for types with user-defined equality or
|
|
% existentially typed constructors are always generated immediately
|
|
% by make_hlds.m.
|
|
not special_pred_for_type_needs_typecheck(ModuleInfo, spec_pred_unify,
|
|
TypeBody).
|
|
|
|
special_pred_for_type_needs_typecheck(ModuleInfo, SpecialPredId, TypeBody) :-
|
|
(
|
|
SpecialPredId = spec_pred_unify,
|
|
type_body_has_user_defined_equality_pred(ModuleInfo, TypeBody,
|
|
unify_compare(_, _))
|
|
;
|
|
SpecialPredId = spec_pred_compare,
|
|
type_body_has_user_defined_equality_pred(ModuleInfo, TypeBody,
|
|
unify_compare(_, UserCmp)),
|
|
UserCmp = yes(_)
|
|
;
|
|
Ctors = TypeBody ^ du_type_ctors,
|
|
list.member(Ctor, Ctors),
|
|
Ctor = ctor(ExistQTVars, _, _, _, _, _),
|
|
ExistQTVars = [_ | _]
|
|
).
|
|
|
|
can_generate_special_pred_clauses_for_type(ModuleInfo, TypeCtor, TypeBody) :-
|
|
(
|
|
TypeBody \= hlds_abstract_type(_)
|
|
;
|
|
% The types which have their unification and comparison
|
|
% predicates defined in private_builtin.m.
|
|
compiler_generated_rtti_for_builtins(ModuleInfo),
|
|
is_builtin_type_special_preds_defined_in_mercury(TypeCtor, _)
|
|
),
|
|
not type_ctor_has_hand_defined_rtti(TypeCtor, TypeBody),
|
|
not type_body_has_user_defined_equality_pred(ModuleInfo, TypeBody,
|
|
abstract_noncanonical_type(_IsSolverType)).
|
|
|
|
is_builtin_type_special_preds_defined_in_mercury(TypeCtor, TypeName) :-
|
|
Builtin = mercury_public_builtin_module,
|
|
TypeCtor = type_ctor(qualified(Builtin, TypeName), 0),
|
|
( TypeName = "int"
|
|
; TypeName = "string"
|
|
; TypeName = "character"
|
|
; TypeName = "float"
|
|
; TypeName = "pred"
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
compiler_generated_rtti_for_builtins(ModuleInfo) :-
|
|
% The compiler generates the rtti for the builtins when we are on the
|
|
% non-C backends. We don't generate the rtti on the C backends as the
|
|
% C runtime contains references to this rtti, so the rtti must be defined
|
|
% in the runtime, not the library.
|
|
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
globals.get_target(Globals, Target),
|
|
( Target = target_csharp
|
|
; Target = target_java
|
|
; Target = target_erlang
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module hlds.special_pred.
|
|
%-----------------------------------------------------------------------------%
|