[m-dev.] `highly ambiguous overloading' ??
Nancy Mazur
Nancy.Mazur at cs.kuleuven.ac.be
Sat Mar 17 02:37:38 AEDT 2001
Hi Hello,
We're trying to figure out the meaning of the next warning:
hlds_pred.m:1918: In clause for predicate `hlds_pred:proc_info_create/12':
hlds_pred.m:1918: warning: highly ambiguous overloading. This may cause
hlds_pred.m:1918: type-checking to be very slow. It may also make your code
hlds_pred.m:1918: difficult to understand.
I've just added an additional field to the proc_info type, and got
that warning.
What's wrong here?
Nancy
PS: in attach, the hlds_pred.m file on which the compiler complains.
-------------- next part --------------
%-----------------------------------------------------------------------------%
% Copyright (C) 1996-2001 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.
%-----------------------------------------------------------------------------%
% This module defines the part of the HLDS that deals with predicates
% and procedures.
% Main authors: fjh, conway.
:- module hlds_pred.
:- interface.
:- import_module prog_data.
:- import_module hlds_data, hlds_goal, hlds_module, instmap, term_util.
:- import_module mode_errors.
:- import_module globals.
:- import_module bool, list, set, map, std_util, term, varset.
:- import_module pa_alias_as, pa_datastruct.
:- import_module sr_data.
:- implementation.
% Parse tree modules.
:- import_module prog_util.
% HLDS modules.
:- import_module code_aux, goal_util, make_hlds.
:- import_module inst_match, mode_util, type_util.
% Misc
:- import_module options.
% Standard library modules.
:- import_module int, string, require, assoc_list.
%-----------------------------------------------------------------------------%
:- interface.
% A proc_id is the name of a mode within a particular predicate -
% not to be confused with a mode_id, which is the name of a
% user-defined mode.
:- type pred_id.
:- type proc_id.
:- pred hlds_pred__initial_pred_id(pred_id).
:- mode hlds_pred__initial_pred_id(out) is det.
:- pred hlds_pred__initial_proc_id(proc_id).
:- mode hlds_pred__initial_proc_id(out) is det.
:- pred hlds_pred__next_pred_id(pred_id, pred_id).
:- mode hlds_pred__next_pred_id(in, out) is det.
:- pred hlds_pred__next_proc_id(proc_id, proc_id).
:- mode hlds_pred__next_proc_id(in, out) is det.
:- pred pred_id_to_int(pred_id, int).
:- mode pred_id_to_int(in, out) is det.
:- mode pred_id_to_int(out, in) is det.
:- pred proc_id_to_int(proc_id, int).
:- mode proc_id_to_int(in, out) is det.
:- mode proc_id_to_int(out, in) is det.
% For semidet complicated unifications with mode (in, in),
% these are defined to have the same proc_id (0). This
% returns that proc_id.
:- pred hlds_pred__in_in_unification_proc_id(proc_id).
:- mode hlds_pred__in_in_unification_proc_id(out) is det.
% Return an invalid pred_id. Used to initialize the pred_id
% in call(...) goals before we do typechecking or when type-checking
% finds that there was no predicate which matched the call.
:- pred invalid_pred_id(pred_id).
:- mode invalid_pred_id(out) is det.
:- pred invalid_proc_id(proc_id).
:- mode invalid_proc_id(out) is det.
:- type pred_info.
:- type proc_info.
:- type proc_table == map(proc_id, proc_info).
:- type call_id
---> call(simple_call_id)
; generic_call(generic_call_id)
.
:- type generic_call_id
---> higher_order(pred_or_func, arity)
; class_method(class_id, simple_call_id)
; aditi_builtin(aditi_builtin, simple_call_id)
.
:- type simple_call_id == pair(pred_or_func, sym_name_and_arity).
:- type pred_proc_id ---> proc(pred_id, proc_id).
:- type pred_proc_list == list(pred_proc_id).
%-----------------------------------------------------------------------------%
% This is used for a closure executed top-down on the Aditi
% side of the connection.
% These expression numbers are stored in the proc_info - the owner
% and module name from the pred_info are also required to completely
% identify the expressions.
:- type rl_exprn_id == int.
%-----------------------------------------------------------------------------%
% The clauses_info structure contains the clauses for a predicate
% after conversion from the item_list by make_hlds.m.
% Typechecking is performed on the clauses info, then the clauses
% are copied to create the proc_info for each procedure.
% After mode analysis the clauses and the procedure goals are not
% guaranteed to be the same, and the clauses are only kept so that
% the optimized goal can be compared with the original in HLDS dumps.
:- type clauses_info
---> clauses_info(
varset :: prog_varset,
% variable names
explicit_vartypes :: vartypes,
% variable types from
% explicit
% qualifications
tvar_name_map :: tvar_name_map,
% map from variable
% name to type variable
% for the type
% variables occurring
% in the argument
% types. This is used
% to process explicit
% type qualifications.
vartypes :: vartypes,
% variable types
% inferred by
% typecheck.m.
headvars :: list(prog_var),
% head vars
clauses :: list(clause),
% the following two
% fields are computed
% by polymorphism.m
clause_type_info_varmap :: type_info_varmap,
clause_typeclass_info_varmap :: typeclass_info_varmap
).
:- type vartypes == map(prog_var, type).
:- type tvar_name_map == map(string, tvar).
:- pred clauses_info_varset(clauses_info, prog_varset).
:- mode clauses_info_varset(in, out) is det.
% This partial map holds the types specified by any explicit
% type qualifiers in the clauses.
:- pred clauses_info_explicit_vartypes(clauses_info, vartypes).
:- mode clauses_info_explicit_vartypes(in, out) is det.
% This map contains the types of all the variables, as inferred
% by typecheck.m.
:- pred clauses_info_vartypes(clauses_info, vartypes).
:- mode clauses_info_vartypes(in, out) is det.
:- pred clauses_info_type_info_varmap(clauses_info, type_info_varmap).
:- mode clauses_info_type_info_varmap(in, out) is det.
:- pred clauses_info_typeclass_info_varmap(clauses_info,
typeclass_info_varmap).
:- mode clauses_info_typeclass_info_varmap(in, out) is det.
:- pred clauses_info_headvars(clauses_info, list(prog_var)).
:- mode clauses_info_headvars(in, out) is det.
:- pred clauses_info_clauses(clauses_info, list(clause)).
:- mode clauses_info_clauses(in, out) is det.
:- pred clauses_info_set_headvars(clauses_info, list(prog_var), clauses_info).
:- mode clauses_info_set_headvars(in, in, out) is det.
:- pred clauses_info_set_clauses(clauses_info, list(clause), clauses_info).
:- mode clauses_info_set_clauses(in, in, out) is det.
:- pred clauses_info_set_varset(clauses_info, prog_varset, clauses_info).
:- mode clauses_info_set_varset(in, in, out) is det.
% This partial map holds the types specified by any explicit
% type qualifiers in the clauses.
:- pred clauses_info_set_explicit_vartypes(clauses_info, vartypes,
clauses_info).
:- mode clauses_info_set_explicit_vartypes(in, in, out) is det.
% This map contains the types of all the variables, as inferred
% by typecheck.m.
:- pred clauses_info_set_vartypes(clauses_info, vartypes,
clauses_info).
:- mode clauses_info_set_vartypes(in, in, out) is det.
:- pred clauses_info_set_type_info_varmap(clauses_info, type_info_varmap,
clauses_info).
:- mode clauses_info_set_type_info_varmap(in, in, out) is det.
:- pred clauses_info_set_typeclass_info_varmap(clauses_info,
typeclass_info_varmap, clauses_info).
:- mode clauses_info_set_typeclass_info_varmap(in, in, out) is det.
:- type clause ---> clause(
list(proc_id), % modes for which
% this clause applies
% (empty list means
% it applies to all
% clauses)
hlds_goal, % Body
prog_context
).
%-----------------------------------------------------------------------------%
% The type of goals that have been given for a pred.
:- type goal_type ---> pragmas % pragma foreign_code(...)
; clauses
; (assertion)
; none.
% Note: `liveness' and `liveness_info' record liveness in the sense
% used by code generation. This is *not* the same thing as the notion
% of liveness used by mode analysis! See compiler/notes/glossary.html.
:- type liveness_info == set(prog_var). % The live variables
:- type liveness ---> live
; dead.
:- type arg_info ---> arg_info(
arg_loc, % stored location
arg_mode % mode of top functor
).
:- type arg_mode ---> top_in
; top_out
; top_unused.
:- type arg_loc == int.
% The type `import_status' describes whether an entity (a predicate,
% type, inst, or mode) is local to the current module, exported from
% the current module, or imported from some other module.
% Only predicates can have status pseudo_exported or pseudo_imported.
% Only types can have status abstract_exported or abstract_imported.
:- type import_status
---> external(section)
% Declared `:- external'.
% This means that the implementation
% for this procedure will be provided
% by some external source, rather than
% via Mercury clauses (including
% `pragma foreign_code' clauses).
% It can be through the use of another
% language, or it could be through some
% other method we haven't thought of yet.
; imported(section)
% defined in the interface of some other module
; opt_imported % defined in the optimization
% interface of another module
; abstract_imported % describes a type with only an abstract
% declaration imported, maybe with the body
% of the type imported from a .opt file
; pseudo_imported % this is used for entities that are defined
% in the interface of some other module but
% for which we may generate some code in
% this module - in particular, this is used
% for unification predicates (see comments in
% unify_proc.m)
; exported % defined in the interface of this module
; opt_exported % a local item for which the import-status
% has been changed due to its presence in
% the .opt files
% (intermod__adjust_pred_import_status)
; abstract_exported % describes a type with only an abstract
% declaration exported
; pseudo_exported % the converse of pseudo_imported
% this means that only the (in, in) mode
% of a unification is exported
; exported_to_submodules
% defined in the implementation of this module,
% and thus in a sense local,
% but the module contains sub-modules,
% so the entity needs to be exported
% to those sub-modules
; local. % defined in the implementation of this module,
% and the module does not contain any
% sub-modules.
% returns yes if the status indicates that the item was
% in any way exported -- that is, if it could be used
% by any other module, or by sub-modules of this module.
:- pred status_is_exported(import_status::in, bool::out) is det.
% returns yes if the status indicates that the item was
% in any way imported -- that is, if it was defined in
% some other module, or in a sub-module of this module.
% This is the opposite of status_defined_in_this_module.
:- pred status_is_imported(import_status::in, bool::out) is det.
% returns yes if the status indicates that the item was
% defined in this module. This is the opposite of
% status_is_imported.
:- pred status_defined_in_this_module(import_status::in, bool::out) is det.
:- pred import_status_to_minimal_string(import_status::in, string::out)
is det.
% Predicates can be marked with various boolean flags, called
% "markers".
% an abstract set of markers.
:- type pred_markers.
:- type marker
---> infer_type % Requests type inference for the predicate
% These markers are inserted by make_hlds
% for undeclared predicates.
; infer_modes % Requests mode inference for the predicate
% These markers are inserted by make_hlds
% for undeclared predicates.
; obsolete % Requests warnings if this predicate is used.
% Used for pragma(obsolete).
; inline % Requests that this predicate be inlined.
% Used for pragma(inline).
; no_inline % Requests that this be predicate not be
% inlined.
% Used for pragma(no_inline).
% Conflicts with `inline' marker.
% The default flags for Aditi predicates are
% aditi, dnf, supp_magic, psn and memo.
; dnf % Requests that this predicate be transformed
% into disjunctive normal form.
; aditi % Generate bottom-up Aditi-RL for this
% predicate.
; (aditi_top_down)
% Generate top-down Aditi-RL, not C, for this
% predicate. This is used for the builtin
% `delete' predicate - the closure is used
% to select which tuples are to be deleted.
; base_relation % This predicate is an Aditi base relation.
% `naive' and `psn' are mutually exclusive.
; naive % Use naive evaluation of this Aditi predicate.
; psn % Use predicate semi-naive evaluation of this
% Aditi predicate.
; aditi_memo % Requests that this Aditi predicate be
% evaluated using memoing. This has no
% relation to eval_method field of the
% pred_info, which is ignored for Aditi
% predicates.
; aditi_no_memo % Ensure that this Aditi predicate
% is not memoed.
% `context' and `supp_magic' are mutually
% exclusive. One of them must be performed
% on all Aditi predicates. `supp_magic'
% is the default
; supp_magic % Perform the supplementary magic sets
% transformation on this predicate. See magic.m
; context % Perform the context transformation on
% the predicate. See context.m
; generate_inline % Used for small Aditi predicates which
% project a relation to be used as input to a
% call to an Aditi predicate in a lower SCC.
% The goal for the predicate should consist
% of fail, true or a single rule.
% These relations are never memoed.
% The reason for this marker is explained
% where it is introduced in
% magic_util__create_closure.
; class_method % Requests that this predicate be transformed
% into the appropriate call to a class method
; class_instance_method
% This predicate was automatically
% generated for the implementation of
% a class method for an instance.
; named_class_instance_method
% This predicate was automatically
% generated for the implementation of
% a class method for an instance,
% and the instance was defined using the
% named syntax (e.g. "pred(...) is ...")
% rather than the clause syntax.
% (For such predicates, we output slightly
% different error messages.)
; (impure) % Requests that no transformation that would
% be inappropriate for impure code be
% performed on calls to this predicate. This
% includes reordering calls to it relative to
% other goals (in both conjunctions and
% disjunctions), and removing redundant calls
% to it.
; (semipure) % Requests that no transformation that would
% be inappropriate for semipure code be
% performed on calls to this predicate. This
% includes removing redundant calls to it on
% different sides of an impure goal.
; promised_pure % Requests that calls to this predicate be
% transformed as usual, despite any impure
% or semipure markers present.
% The terminates and does_not_terminate
% pragmas are kept as markers to ensure
% that conflicting declarations are not
% made by the user. Otherwise, the
% information could be added to the
% ProcInfos directly.
; terminates % The user guarantees that this predicate
% will terminate for all (finite?) input
; does_not_terminate
% States that this predicate does not
% terminate. This is useful for pragma
% foreign_code, which the compiler assumes to be
% terminating.
; check_termination
% The user requires the compiler to guarantee
% the termination of this predicate.
% If the compiler cannot guarantee termination
% then it must give an error message.
.
% Aditi predicates are identified by their owner as well as
% module, name and arity.
:- type aditi_owner == string.
% The constraint_proof_map is a map which for each type class
% constraint records how/why that constraint was satisfied.
% This information is used to determine how to construct the
% typeclass_info for that constraint.
:- type constraint_proof_map == map(class_constraint, constraint_proof).
% Describes the class constraints on an instance method
% implementation. This information is used by polymorphism.m
% to ensure that the type_info and typeclass_info arguments
% are added in the order they will be passed in by
% do_call_class_method.
:- type instance_method_constraints
---> instance_method_constraints(
class_id,
list(type), % The types in the head of the
% instance declaration.
list(class_constraint), % The universal constraints
% on the instance declaration.
class_constraints % The contraints on the method's
% type declaration in the
% `:- typeclass' declaration.
).
% A typeclass_info_varmap is a map which for each type class constraint
% records which variable contains the typeclass_info for that
% constraint.
:- type typeclass_info_varmap == map(class_constraint, prog_var).
% A type_info_varmap is a map which for each type variable
% records where the type_info for that type variable is stored.
:- type type_info_varmap == map(tvar, type_info_locn).
% A type_info_locn specifies how to access a type_info.
:- type type_info_locn
---> type_info(prog_var)
% It is a normal type_info, i.e. the type
% is not constrained.
; typeclass_info(prog_var, int).
% The type_info is packed inside a
% typeclass_info. If the int is N, it is
% the Nth type_info inside the typeclass_info,
% but there may be several superclass pointers
% before the block of type_infos, so it won't
% be the Nth word of the typeclass_info.
%
% To find the type_info inside the
% typeclass_info, use the predicate
% type_info_from_typeclass_info from Mercury
% code; from C code use the macro
% MR_typeclass_info_superclass_info.
% type_info_locn_var(TypeInfoLocn, Var):
% Var is the variable corresponding to the TypeInfoLocn. Note
% that this does *not* mean that Var is a type_info; it may be
% a typeclass_info in which the type_info is nested.
:- pred type_info_locn_var(type_info_locn::in, prog_var::out) is det.
:- pred type_info_locn_set_var(type_info_locn::in, prog_var::in,
type_info_locn::out) is det.
% hlds_pred__define_new_pred(Goal, CallGoal, Args, ExtraArgs, InstMap,
% PredName, TVarSet, VarTypes, ClassContext, TVarMap, TCVarMap,
% VarSet, Markers, Owner, IsAddressTaken,
% ModuleInfo0, ModuleInfo, PredProcId)
%
% Create a new predicate for the given goal, returning a goal to
% call the created predicate. ExtraArgs is the list of extra
% type_infos and typeclass_infos required by typeinfo liveness
% which were added to the front of the argument list.
:- pred hlds_pred__define_new_pred(hlds_goal, hlds_goal, list(prog_var),
list(prog_var), instmap, string, tvarset, vartypes,
class_constraints, type_info_varmap, typeclass_info_varmap,
prog_varset, inst_varset, pred_markers, aditi_owner,
is_address_taken, module_info, module_info, pred_proc_id).
:- mode hlds_pred__define_new_pred(in, out, in, out, in, in, in, in, in,
in, in, in, in, in, in, in, in, out, out) is det.
% Various predicates for accessing the information stored in the
% pred_id and pred_info data structures.
:- pred pred_info_init(module_name, sym_name, arity, tvarset, existq_tvars,
list(type), condition, prog_context, clauses_info, import_status,
pred_markers, goal_type, pred_or_func, class_constraints,
constraint_proof_map, aditi_owner, pred_info).
:- mode pred_info_init(in, in, in, in, in, in, in, in, in, in, in, in, in,
in, in, in, out) is det.
:- pred pred_info_create(module_name, sym_name, tvarset, existq_tvars,
list(type), condition, prog_context, import_status, pred_markers,
pred_or_func, class_constraints, aditi_owner, set(assert_id),
proc_info, proc_id, pred_info).
:- mode pred_info_create(in, in, in, in, in, in, in, in, in, in, in, in, in,
in, out, out) is det.
:- pred pred_info_module(pred_info, module_name).
:- mode pred_info_module(in, out) is det.
:- pred pred_info_name(pred_info, string).
:- mode pred_info_name(in, out) is det.
% pred_info_arity returns the arity of the predicate
% *not* counting inserted type_info arguments for polymorphic preds.
:- pred pred_info_arity(pred_info, arity).
:- mode pred_info_arity(in, out) is det.
% Return a list of all the proc_ids for the valid modes
% of this predicate. This does not include candidate modes
% that were generated during mode inference but which mode
% inference found were not valid modes.
:- pred pred_info_procids(pred_info, list(proc_id)).
:- mode pred_info_procids(in, out) is det.
% Return a list of the proc_ids for all the modes
% of this predicate, including invalid modes.
:- pred pred_info_all_procids(pred_info, list(proc_id)).
:- mode pred_info_all_procids(in, out) is det.
% Return a list of the proc_ids for all the valid modes
% of this predicate that are not imported.
:- pred pred_info_non_imported_procids(pred_info, list(proc_id)).
:- mode pred_info_non_imported_procids(in, out) is det.
% Return a list of the proc_ids for all the modes
% of this predicate that are not imported
% (including invalid modes).
:- pred pred_info_all_non_imported_procids(pred_info, list(proc_id)).
:- mode pred_info_all_non_imported_procids(in, out) is det.
% Return a list of the proc_ids for all the valid modes
% of this predicate that are exported.
:- pred pred_info_exported_procids(pred_info, list(proc_id)).
:- mode pred_info_exported_procids(in, out) is det.
:- pred pred_info_arg_types(pred_info, list(type)).
:- mode pred_info_arg_types(in, out) is det.
:- pred pred_info_arg_types(pred_info, tvarset, existq_tvars, list(type)).
:- mode pred_info_arg_types(in, out, out, out) is det.
:- pred pred_info_set_arg_types(pred_info, tvarset, existq_tvars, list(type),
pred_info).
:- mode pred_info_set_arg_types(in, in, in, in, out) is det.
:- pred pred_info_get_exist_quant_tvars(pred_info, existq_tvars).
:- mode pred_info_get_exist_quant_tvars(in, out) is det.
:- pred pred_info_get_univ_quant_tvars(pred_info, existq_tvars).
:- mode pred_info_get_univ_quant_tvars(in, out) is det.
:- type head_type_params == list(tvar).
:- pred pred_info_get_head_type_params(pred_info, head_type_params).
:- mode pred_info_get_head_type_params(in, out) is det.
:- pred pred_info_set_head_type_params(pred_info, head_type_params, pred_info).
:- mode pred_info_set_head_type_params(in, in, out) is det.
:- pred pred_info_get_unproven_body_constraints(pred_info,
list(class_constraint)).
:- mode pred_info_get_unproven_body_constraints(in, out) is det.
:- pred pred_info_set_unproven_body_constraints(pred_info,
list(class_constraint), pred_info).
:- mode pred_info_set_unproven_body_constraints(in, in, out) is det.
:- pred pred_info_clauses_info(pred_info, clauses_info).
:- mode pred_info_clauses_info(in, out) is det.
:- pred pred_info_set_clauses_info(pred_info, clauses_info, pred_info).
:- mode pred_info_set_clauses_info(in, in, out) is det.
:- pred pred_info_procedures(pred_info, proc_table).
:- mode pred_info_procedures(in, out) is det.
:- pred pred_info_set_procedures(pred_info, proc_table, pred_info).
:- mode pred_info_set_procedures(in, in, out) is det.
:- pred pred_info_context(pred_info, prog_context).
:- mode pred_info_context(in, out) is det.
:- pred pred_info_import_status(pred_info::in, import_status::out) is det.
:- pred pred_info_is_imported(pred_info::in) is semidet.
:- pred pred_info_is_pseudo_imported(pred_info::in) is semidet.
% pred_info_is_exported does *not* include predicates which are
% exported_to_submodules or pseudo_exported
:- pred pred_info_is_exported(pred_info::in) is semidet.
:- pred pred_info_is_opt_exported(pred_info::in) is semidet.
:- pred pred_info_is_exported_to_submodules(pred_info::in) is semidet.
:- pred pred_info_is_pseudo_exported(pred_info::in) is semidet.
% procedure_is_exported includes all modes of exported or
% exported_to_submodules predicates, plus the in-in mode
% for pseudo_exported unification predicates.
:- pred procedure_is_exported(pred_info::in, proc_id::in) is semidet.
% Set the import_status of the predicate to `imported'.
% This is used for `:- external(foo/2).' declarations.
:- pred pred_info_mark_as_external(pred_info::in, pred_info::out) is det.
:- pred pred_info_set_import_status(pred_info::in, import_status::in,
pred_info::out) is det.
:- pred pred_info_typevarset(pred_info, tvarset).
:- mode pred_info_typevarset(in, out) is det.
:- pred pred_info_set_typevarset(pred_info, tvarset, pred_info).
:- mode pred_info_set_typevarset(in, in, out) is det.
:- pred pred_info_get_goal_type(pred_info, goal_type).
:- mode pred_info_get_goal_type(in, out) is det.
:- pred pred_info_set_goal_type(pred_info, goal_type, pred_info).
:- mode pred_info_set_goal_type(in, in, out) is det.
% Succeeds if there was a `:- pragma inline(...)' declaration
% for this predicate. Note that the compiler may decide
% to inline a predicate even if there was no pragma inline(...)
% declaration for that predicate.
:- pred pred_info_requested_inlining(pred_info).
:- mode pred_info_requested_inlining(in) is semidet.
% Succeeds if there was a `:- pragma no_inline(...)' declaration
% for this predicate.
:- pred pred_info_requested_no_inlining(pred_info).
:- mode pred_info_requested_no_inlining(in) is semidet.
% N-ary functions are converted into N+1-ary predicates.
% (Clauses are converted in make_hlds, but calls to functions
% cannot be converted until after type-checking, once we have
% resolved overloading. So we do that during mode analysis.)
% The `is_pred_or_func' field of the pred_info records whether
% a pred_info is really for a predicate or whether it is for
% what was originally a function.
:- pred pred_info_get_is_pred_or_func(pred_info, pred_or_func).
:- mode pred_info_get_is_pred_or_func(in, out) is det.
:- pred pred_info_get_class_context(pred_info, class_constraints).
:- mode pred_info_get_class_context(in, out) is det.
:- pred pred_info_set_class_context(pred_info, class_constraints, pred_info).
:- mode pred_info_set_class_context(in, in, out) is det.
:- pred pred_info_get_constraint_proofs(pred_info, constraint_proof_map).
:- mode pred_info_get_constraint_proofs(in, out) is det.
:- pred pred_info_set_constraint_proofs(pred_info, constraint_proof_map,
pred_info).
:- mode pred_info_set_constraint_proofs(in, in, out) is det.
:- pred pred_info_get_aditi_owner(pred_info, string).
:- mode pred_info_get_aditi_owner(in, out) is det.
:- pred pred_info_set_aditi_owner(pred_info, string, pred_info).
:- mode pred_info_set_aditi_owner(in, in, out) is det.
:- pred pred_info_get_indexes(pred_info, list(index_spec)).
:- mode pred_info_get_indexes(in, out) is det.
:- pred pred_info_set_indexes(pred_info, list(index_spec), pred_info).
:- mode pred_info_set_indexes(in, in, out) is det.
:- pred pred_info_get_assertions(pred_info, set(assert_id)).
:- mode pred_info_get_assertions(in, out) is det.
:- pred pred_info_set_assertions(pred_info, set(assert_id), pred_info).
:- mode pred_info_set_assertions(in, in, out) is det.
:- pred pred_info_get_maybe_instance_method_constraints(pred_info,
maybe(instance_method_constraints)).
:- mode pred_info_get_maybe_instance_method_constraints(in, out) is det.
:- pred pred_info_set_maybe_instance_method_constraints(pred_info,
maybe(instance_method_constraints), pred_info).
:- mode pred_info_set_maybe_instance_method_constraints(in, in, out) is det.
:- pred pred_info_get_purity(pred_info, purity).
:- mode pred_info_get_purity(in, out) is det.
:- pred pred_info_get_promised_pure(pred_info, bool).
:- mode pred_info_get_promised_pure(in, out) is det.
:- pred purity_to_markers(purity, pred_markers).
:- mode purity_to_markers(in, out) is det.
:- pred pred_info_get_markers(pred_info, pred_markers).
:- mode pred_info_get_markers(in, out) is det.
:- pred pred_info_set_markers(pred_info, pred_markers, pred_info).
:- mode pred_info_set_markers(in, in, out) is det.
:- pred pred_info_get_call_id(pred_info, simple_call_id).
:- mode pred_info_get_call_id(in, out) is det.
% create an empty set of markers
:- pred init_markers(pred_markers).
:- mode init_markers(out) is det.
% check if a particular is in the set
:- pred check_marker(pred_markers, marker).
:- mode check_marker(in, in) is semidet.
% add a marker to the set
:- pred add_marker(pred_markers, marker, pred_markers).
:- mode add_marker(in, in, out) is det.
% remove a marker from the set
:- pred remove_marker(pred_markers, marker, pred_markers).
:- mode remove_marker(in, in, out) is det.
% convert the set to a list
:- pred markers_to_marker_list(pred_markers, list(marker)).
:- mode markers_to_marker_list(in, out) is det.
:- pred marker_list_to_markers(list(marker), pred_markers).
:- mode marker_list_to_markers(in, out) is det.
%-----------------------------------------------------------------------------%
:- implementation.
:- type pred_id == int.
:- type proc_id == int.
hlds_pred__initial_pred_id(0).
hlds_pred__initial_proc_id(0).
hlds_pred__next_pred_id(PredId, NextPredId) :-
NextPredId is PredId + 1.
hlds_pred__next_proc_id(ProcId, NextProcId) :-
NextProcId is ProcId + 1.
pred_id_to_int(PredId, PredId).
proc_id_to_int(ProcId, ProcId).
hlds_pred__in_in_unification_proc_id(0).
invalid_pred_id(-1).
invalid_proc_id(-1).
status_is_exported(imported(_), no).
status_is_exported(external(_), no).
status_is_exported(abstract_imported, no).
status_is_exported(pseudo_imported, no).
status_is_exported(opt_imported, no).
status_is_exported(exported, yes).
status_is_exported(opt_exported, yes).
status_is_exported(abstract_exported, yes).
status_is_exported(pseudo_exported, yes).
status_is_exported(exported_to_submodules, yes).
status_is_exported(local, no).
status_is_imported(Status, Imported) :-
status_defined_in_this_module(Status, InThisModule),
bool__not(InThisModule, Imported).
status_defined_in_this_module(imported(_), no).
status_defined_in_this_module(external(_), no).
status_defined_in_this_module(abstract_imported, no).
status_defined_in_this_module(pseudo_imported, no).
status_defined_in_this_module(opt_imported, no).
status_defined_in_this_module(exported, yes).
status_defined_in_this_module(opt_exported, yes).
status_defined_in_this_module(abstract_exported, yes).
status_defined_in_this_module(pseudo_exported, yes).
status_defined_in_this_module(exported_to_submodules, yes).
status_defined_in_this_module(local, yes).
import_status_to_minimal_string(imported(_), "imported").
import_status_to_minimal_string(opt_imported, "opt_imported").
import_status_to_minimal_string(abstract_imported, "abstract_imported").
import_status_to_minimal_string(pseudo_imported, "pseudo_imported").
import_status_to_minimal_string(exported, "exported").
import_status_to_minimal_string(opt_exported, "opt_exported").
import_status_to_minimal_string(abstract_exported, "abstract_exported").
import_status_to_minimal_string(pseudo_exported, "pseudo_exported").
import_status_to_minimal_string(exported_to_submodules,
"exported_to_submodules").
import_status_to_minimal_string(local, "local").
import_status_to_minimal_string(external(_), "external").
% The information specific to a predicate, as opposed to a procedure.
% (Functions count as predicates.)
:- type pred_info
---> predicate(
decl_typevarset :: tvarset,
% names of type vars
% in the predicate's type decl
arg_types :: list(type),
% argument types
condition :: condition,
% formal specification
% (not used)
clauses_info :: clauses_info,
procedures :: proc_table,
context :: prog_context,
% the location (line #)
% of the :- pred decl.
(module) :: module_name,
% module in which pred occurs
name :: string,
% predicate name
arity :: arity,
% the arity of the pred
% (*not* counting any inserted
% type_info arguments)
import_status :: import_status,
typevarset :: tvarset,
% names of type vars
% in the predicate's type decl
% or in the variable type assignments
goal_type :: goal_type,
% whether the goals seen so far for
% this pred are clauses,
% pragma foreign_code(...) decs, or none
markers :: pred_markers,
% various boolean flags
is_pred_or_func :: pred_or_func,
% whether this "predicate" was really
% a predicate or a function
class_context :: class_constraints,
% the class constraints on the
% type variables in the predicate's
% type declaration
constraint_proofs :: constraint_proof_map,
% explanations of how redundant
% constraints were eliminated. These
% are needed by polymorphism.m to
% work out where to get the
% typeclass_infos from.
% Computed during type checking.
exist_quant_tvars :: existq_tvars,
% the set of existentially quantified
% type variables in the predicate's
% type decl
head_type_params :: head_type_params,
% The set of type variables which the
% body of the predicate can't bind,
% and whose type_infos are produced
% elsewhere. This includes
% universally quantified head types
% (the type_infos are passed in)
% plus existentially quantified types
% in preds called from the body
% (the type_infos are returned from
% the called preds).
% Computed during type checking.
unproven_body_constraints :: list(class_constraint),
% unproven class constraints on type
% variables in the predicate's body,
% if any (if this remains non-empty
% after type checking has finished,
% post_typecheck.m will report a type
% error).
aditi_owner :: aditi_owner,
% The owner of this predicate if
% it is an Aditi predicate. Set to
% the value of --aditi-user if no
% `:- pragma owner' declaration exists.
indexes :: list(index_spec),
% Indexes if this predicate is
% an Aditi base relation, ignored
% otherwise.
assertions :: set(assert_id),
% List of assertions which
% mention this predicate.
maybe_instance_method_constraints
:: maybe(instance_method_constraints)
% If this predicate is a class method
% implementation, record extra
% information about the class context
% to allow polymorphism.m to
% correctly set up the extra
% type_info and typeclass_info
% arguments.
).
pred_info_init(ModuleName, SymName, Arity, TypeVarSet, ExistQVars, Types,
Cond, Context, ClausesInfo, Status, Markers, GoalType,
PredOrFunc, ClassContext, ClassProofs, User, PredInfo) :-
map__init(Procs),
unqualify_name(SymName, PredName),
sym_name_get_module_name(SymName, ModuleName, PredModuleName),
term__vars_list(Types, TVars),
list__delete_elems(TVars, ExistQVars, HeadTypeParams),
UnprovenBodyConstraints = [],
Indexes = [],
set__init(Assertions),
MaybeInstanceConstraints = no,
PredInfo = predicate(TypeVarSet, Types, Cond, ClausesInfo, Procs,
Context, PredModuleName, PredName, Arity, Status, TypeVarSet,
GoalType, Markers, PredOrFunc, ClassContext, ClassProofs,
ExistQVars, HeadTypeParams, UnprovenBodyConstraints, User,
Indexes, Assertions, MaybeInstanceConstraints).
pred_info_create(ModuleName, SymName, TypeVarSet, ExistQVars, Types, Cond,
Context, Status, Markers, PredOrFunc, ClassContext, User,
Assertions, ProcInfo, ProcId, PredInfo) :-
map__init(Procs0),
proc_info_declared_determinism(ProcInfo, MaybeDetism),
next_mode_id(Procs0, MaybeDetism, ProcId),
map__det_insert(Procs0, ProcId, ProcInfo, Procs),
list__length(list__filter(isnt(is_introduced_type_info_type), Types),
Arity),
proc_info_varset(ProcInfo, VarSet),
proc_info_vartypes(ProcInfo, VarTypes),
proc_info_headvars(ProcInfo, HeadVars),
proc_info_typeinfo_varmap(ProcInfo, TypeInfoMap),
proc_info_typeclass_info_varmap(ProcInfo, TypeClassInfoMap),
unqualify_name(SymName, PredName),
% The empty list of clauses is a little white lie.
Clauses = [],
map__init(TVarNameMap),
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap,
VarTypes, HeadVars, Clauses, TypeInfoMap, TypeClassInfoMap),
map__init(ClassProofs),
term__vars_list(Types, TVars),
list__delete_elems(TVars, ExistQVars, HeadTypeParams),
UnprovenBodyConstraints = [],
Indexes = [],
MaybeInstanceConstraints = no,
PredInfo = predicate(TypeVarSet, Types, Cond, ClausesInfo, Procs,
Context, ModuleName, PredName, Arity, Status, TypeVarSet,
clauses, Markers, PredOrFunc, ClassContext, ClassProofs,
ExistQVars, HeadTypeParams, UnprovenBodyConstraints, User,
Indexes, Assertions, MaybeInstanceConstraints).
pred_info_all_procids(PredInfo, ProcIds) :-
ProcTable = PredInfo ^ procedures,
map__keys(ProcTable, ProcIds).
pred_info_procids(PredInfo, ValidProcIds) :-
pred_info_all_procids(PredInfo, AllProcIds),
ProcTable = PredInfo ^ procedures,
IsValid = (pred(ProcId::in) is semidet :-
ProcInfo = map__lookup(ProcTable, ProcId),
proc_info_is_valid_mode(ProcInfo)),
list__filter(IsValid, AllProcIds, ValidProcIds).
pred_info_non_imported_procids(PredInfo, ProcIds) :-
pred_info_import_status(PredInfo, ImportStatus),
( ImportStatus = imported(_) ->
ProcIds = []
; ImportStatus = external(_) ->
ProcIds = []
; ImportStatus = pseudo_imported ->
pred_info_procids(PredInfo, ProcIds0),
% for pseduo_imported preds, procid 0 is imported
list__delete_all(ProcIds0, 0, ProcIds)
;
pred_info_procids(PredInfo, ProcIds)
).
pred_info_all_non_imported_procids(PredInfo, ProcIds) :-
pred_info_import_status(PredInfo, ImportStatus),
( ImportStatus = imported(_) ->
ProcIds = []
; ImportStatus = external(_) ->
ProcIds = []
; ImportStatus = pseudo_imported ->
pred_info_all_procids(PredInfo, ProcIds0),
% for pseduo_imported preds, procid 0 is imported
list__delete_all(ProcIds0, 0, ProcIds)
;
pred_info_all_procids(PredInfo, ProcIds)
).
pred_info_exported_procids(PredInfo, ProcIds) :-
pred_info_import_status(PredInfo, ImportStatus),
(
( ImportStatus = exported
; ImportStatus = opt_exported
; ImportStatus = exported_to_submodules
)
->
pred_info_procids(PredInfo, ProcIds)
;
ImportStatus = pseudo_exported
->
ProcIds = [0]
;
ProcIds = []
).
pred_info_clauses_info(PredInfo, PredInfo^clauses_info).
pred_info_set_clauses_info(PredInfo, X, PredInfo^clauses_info := X).
pred_info_arg_types(PredInfo, ArgTypes) :-
pred_info_arg_types(PredInfo, _TypeVars, _ExistQVars, ArgTypes).
pred_info_arg_types(PredInfo, PredInfo^decl_typevarset,
PredInfo^exist_quant_tvars, PredInfo^arg_types).
pred_info_set_arg_types(PredInfo0, TypeVarSet, ExistQVars, ArgTypes,
PredInfo) :-
PredInfo = ((PredInfo0
^decl_typevarset := TypeVarSet)
^exist_quant_tvars := ExistQVars)
^arg_types := ArgTypes.
pred_info_procedures(PredInfo, PredInfo^procedures).
pred_info_set_procedures(PredInfo, X, PredInfo^procedures := X).
pred_info_context(PredInfo, PredInfo^context).
pred_info_module(PredInfo, PredInfo^(module)).
pred_info_name(PredInfo, PredInfo^name).
pred_info_arity(PredInfo, PredInfo^arity).
pred_info_import_status(PredInfo, PredInfo^import_status).
pred_info_is_imported(PredInfo) :-
pred_info_import_status(PredInfo, Status),
( Status = imported(_)
; Status = external(_)
).
pred_info_is_pseudo_imported(PredInfo) :-
pred_info_import_status(PredInfo, ImportStatus),
ImportStatus = pseudo_imported.
pred_info_is_exported(PredInfo) :-
pred_info_import_status(PredInfo, ImportStatus),
ImportStatus = exported.
pred_info_is_opt_exported(PredInfo) :-
pred_info_import_status(PredInfo, ImportStatus),
ImportStatus = opt_exported.
pred_info_is_exported_to_submodules(PredInfo) :-
pred_info_import_status(PredInfo, ImportStatus),
ImportStatus = exported_to_submodules.
pred_info_is_pseudo_exported(PredInfo) :-
pred_info_import_status(PredInfo, ImportStatus),
ImportStatus = pseudo_exported.
procedure_is_exported(PredInfo, ProcId) :-
(
pred_info_is_exported(PredInfo)
;
pred_info_is_opt_exported(PredInfo)
;
pred_info_is_exported_to_submodules(PredInfo)
;
pred_info_is_pseudo_exported(PredInfo),
hlds_pred__in_in_unification_proc_id(ProcId)
).
pred_info_mark_as_external(PredInfo0, PredInfo) :-
status_is_exported(PredInfo0^import_status, Exported),
(
Exported = yes,
PredInfo = PredInfo0^import_status := external(interface)
;
Exported = no,
PredInfo = PredInfo0^import_status := external(implementation)
).
pred_info_set_import_status(PredInfo, X, PredInfo^import_status := X).
pred_info_typevarset(PredInfo, PredInfo^typevarset).
pred_info_set_typevarset(PredInfo, X, PredInfo^typevarset := X).
pred_info_get_goal_type(PredInfo, PredInfo^goal_type).
pred_info_set_goal_type(PredInfo, X, PredInfo^goal_type := X).
pred_info_requested_inlining(PredInfo0) :-
pred_info_get_markers(PredInfo0, Markers),
check_marker(Markers, inline).
pred_info_requested_no_inlining(PredInfo0) :-
pred_info_get_markers(PredInfo0, Markers),
check_marker(Markers, no_inline).
pred_info_get_purity(PredInfo0, Purity) :-
pred_info_get_markers(PredInfo0, Markers),
( check_marker(Markers, (impure)) ->
Purity = (impure)
; check_marker(Markers, (semipure)) ->
Purity = (semipure)
;
Purity = pure
).
pred_info_get_promised_pure(PredInfo0, Promised) :-
pred_info_get_markers(PredInfo0, Markers),
( check_marker(Markers, promised_pure) ->
Promised = yes
;
Promised = no
).
purity_to_markers(pure, []).
purity_to_markers(semipure, [semipure]).
purity_to_markers(impure, [impure]).
pred_info_get_markers(PredInfo, PredInfo^markers).
pred_info_set_markers(PredInfo, X, PredInfo^markers := X).
pred_info_get_is_pred_or_func(PredInfo, PredInfo^is_pred_or_func).
pred_info_set_class_context(PredInfo, X, PredInfo^class_context := X).
pred_info_get_class_context(PredInfo, PredInfo^class_context).
pred_info_set_constraint_proofs(PredInfo, X, PredInfo^constraint_proofs := X).
pred_info_get_constraint_proofs(PredInfo, PredInfo^constraint_proofs).
pred_info_get_exist_quant_tvars(PredInfo, PredInfo^exist_quant_tvars).
pred_info_get_univ_quant_tvars(PredInfo, UnivQVars) :-
pred_info_arg_types(PredInfo, ArgTypes),
term__vars_list(ArgTypes, ArgTypeVars0),
list__sort_and_remove_dups(ArgTypeVars0, ArgTypeVars),
pred_info_get_exist_quant_tvars(PredInfo, ExistQVars),
list__delete_elems(ArgTypeVars, ExistQVars, UnivQVars).
pred_info_get_head_type_params(PredInfo, PredInfo^head_type_params).
pred_info_set_head_type_params(PredInfo, X, PredInfo^head_type_params := X).
pred_info_get_unproven_body_constraints(PredInfo,
PredInfo^unproven_body_constraints).
pred_info_set_unproven_body_constraints(PredInfo, X,
PredInfo^unproven_body_constraints := X).
pred_info_get_aditi_owner(PredInfo, PredInfo^aditi_owner).
pred_info_set_aditi_owner(PredInfo, X, PredInfo^aditi_owner := X).
pred_info_get_indexes(PredInfo, PredInfo^indexes).
pred_info_set_indexes(PredInfo, X, PredInfo^indexes := X).
pred_info_get_assertions(PredInfo, PredInfo^assertions).
pred_info_set_assertions(PredInfo, X, PredInfo^assertions := X).
pred_info_get_maybe_instance_method_constraints(PredInfo,
PredInfo^maybe_instance_method_constraints).
pred_info_set_maybe_instance_method_constraints(PredInfo, X,
PredInfo^maybe_instance_method_constraints := X).
%-----------------------------------------------------------------------------%
pred_info_get_call_id(PredInfo, PredOrFunc - qualified(Module, Name)/Arity) :-
pred_info_get_is_pred_or_func(PredInfo, PredOrFunc),
pred_info_module(PredInfo, Module),
pred_info_name(PredInfo, Name),
pred_info_arity(PredInfo, Arity).
%-----------------------------------------------------------------------------%
type_info_locn_var(type_info(Var), Var).
type_info_locn_var(typeclass_info(Var, _), Var).
type_info_locn_set_var(type_info(_), Var, type_info(Var)).
type_info_locn_set_var(typeclass_info(_, Num), Var, typeclass_info(Var, Num)).
%-----------------------------------------------------------------------------%
:- type pred_markers == list(marker).
init_markers([]).
check_marker(Markers, Marker) :-
list__member(Marker, Markers).
add_marker(Markers, Marker, [Marker | Markers]).
remove_marker(Markers0, Marker, Markers) :-
list__delete_all(Markers0, Marker, Markers).
markers_to_marker_list(Markers, Markers).
marker_list_to_markers(Markers, Markers).
%-----------------------------------------------------------------------------%
clauses_info_varset(CI, CI^varset).
clauses_info_explicit_vartypes(CI, CI^explicit_vartypes).
clauses_info_vartypes(CI, CI^vartypes).
clauses_info_headvars(CI, CI^headvars).
clauses_info_clauses(CI, CI^clauses).
clauses_info_type_info_varmap(CI, CI^clause_type_info_varmap).
clauses_info_typeclass_info_varmap(CI, CI^clause_typeclass_info_varmap).
clauses_info_set_varset(CI, X, CI^varset := X).
clauses_info_set_explicit_vartypes(CI, X, CI^explicit_vartypes := X).
clauses_info_set_vartypes(CI, X, CI^vartypes := X).
clauses_info_set_headvars(CI, X, CI^headvars := X).
clauses_info_set_clauses(CI, X, CI^clauses := X).
clauses_info_set_type_info_varmap(CI, X, CI^clause_type_info_varmap := X).
clauses_info_set_typeclass_info_varmap(CI, X,
CI^clause_typeclass_info_varmap := X).
%-----------------------------------------------------------------------------%
hlds_pred__define_new_pred(Goal0, Goal, ArgVars0, ExtraTypeInfos, InstMap0,
PredName, TVarSet, VarTypes0, ClassContext, TVarMap, TCVarMap,
VarSet0, InstVarSet, Markers, Owner, IsAddressTaken,
ModuleInfo0, ModuleInfo, PredProcId) :-
Goal0 = _GoalExpr - GoalInfo,
goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
instmap__apply_instmap_delta(InstMap0, InstMapDelta, InstMap),
% XXX The set of existentially quantified type variables
% here might not be correct.
ExistQVars = [],
% If interface typeinfo liveness is set, all type_infos for the
% arguments need to be passed in, not just the ones that are used.
% Similarly if the address of a procedure of this predicate is taken,
% so that we can copy the closure.
module_info_globals(ModuleInfo0, Globals),
ExportStatus = local,
non_special_interface_should_use_typeinfo_liveness(ExportStatus,
IsAddressTaken, Globals, TypeInfoLiveness),
( TypeInfoLiveness = yes ->
goal_info_get_nonlocals(GoalInfo, NonLocals),
goal_util__extra_nonlocal_typeinfos(TVarMap, TCVarMap,
VarTypes0, ExistQVars, NonLocals, ExtraTypeInfos0),
set__delete_list(ExtraTypeInfos0, ArgVars0, ExtraTypeInfos1),
set__to_sorted_list(ExtraTypeInfos1, ExtraTypeInfos),
list__append(ExtraTypeInfos, ArgVars0, ArgVars)
;
ArgVars = ArgVars0,
ExtraTypeInfos = []
),
goal_info_get_context(GoalInfo, Context),
goal_info_get_determinism(GoalInfo, Detism),
compute_arg_types_modes(ArgVars, VarTypes0, InstMap0, InstMap,
ArgTypes, ArgModes),
module_info_name(ModuleInfo0, ModuleName),
SymName = qualified(ModuleName, PredName),
% Remove unneeded variables from the vartypes and varset.
goal_util__goal_vars(Goal0, GoalVars0),
set__insert_list(GoalVars0, ArgVars, GoalVars),
map__select(VarTypes0, GoalVars, VarTypes),
varset__select(VarSet0, GoalVars, VarSet),
% Approximate the termination information
% for the new procedure.
( code_aux__goal_cannot_loop(ModuleInfo0, Goal0) ->
TermInfo = yes(cannot_loop)
;
TermInfo = no
),
proc_info_create(VarSet, VarTypes, ArgVars, ArgModes, InstVarSet,
Detism, Goal0, Context, TVarMap, TCVarMap, IsAddressTaken,
ProcInfo0),
proc_info_set_maybe_termination_info(ProcInfo0, TermInfo, ProcInfo),
set__init(Assertions),
pred_info_create(ModuleName, SymName, TVarSet, ExistQVars, ArgTypes,
true, Context, ExportStatus, Markers, predicate, ClassContext,
Owner, Assertions, ProcInfo, ProcId, PredInfo),
module_info_get_predicate_table(ModuleInfo0, PredTable0),
predicate_table_insert(PredTable0, PredInfo, PredId,
PredTable),
module_info_set_predicate_table(ModuleInfo0, PredTable,
ModuleInfo),
GoalExpr = call(PredId, ProcId, ArgVars, not_builtin, no, SymName),
Goal = GoalExpr - GoalInfo,
PredProcId = proc(PredId, ProcId).
:- pred compute_arg_types_modes(list(prog_var)::in, vartypes::in,
instmap::in, instmap::in, list(type)::out, list(mode)::out) is det.
compute_arg_types_modes([], _, _, _, [], []).
compute_arg_types_modes([Var | Vars], VarTypes, InstMap0, InstMap,
[Type | Types], [Mode | Modes]) :-
map__lookup(VarTypes, Var, Type),
instmap__lookup_var(InstMap0, Var, Inst0),
instmap__lookup_var(InstMap, Var, Inst),
Mode = (Inst0 -> Inst),
compute_arg_types_modes(Vars, VarTypes, InstMap0, InstMap,
Types, Modes).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% Various predicates for accessing the proc_info data structure.
:- interface.
:- type is_address_taken
---> address_is_taken
; address_is_not_taken.
:- pred proc_info_init(arity, list(type), list(mode), maybe(list(mode)),
maybe(list(is_live)), maybe(determinism), prog_context,
is_address_taken, proc_info).
:- mode proc_info_init(in, in, in, in, in, in, in, in, out) is det.
:- pred proc_info_set(maybe(determinism), prog_varset, vartypes,
list(prog_var), list(mode), inst_varset, maybe(list(is_live)),
hlds_goal, prog_context, stack_slots, determinism, bool,
list(arg_info), liveness_info, type_info_varmap,
typeclass_info_varmap, maybe(arg_size_info),
maybe(termination_info), is_address_taken, proc_info).
:- mode proc_info_set(in, in, in, in, in, in, in, in, in, in, in, in,
in, in, in, in, in, in, in, out) is det.
:- pred proc_info_create(prog_varset, vartypes, list(prog_var),
list(mode), inst_varset, determinism, hlds_goal, prog_context,
type_info_varmap, typeclass_info_varmap, is_address_taken, proc_info).
:- mode proc_info_create(in, in, in, in, in, in, in, in, in, in, in, out)
is det.
:- pred proc_info_set_body(proc_info, prog_varset, vartypes,
list(prog_var), hlds_goal, type_info_varmap,
typeclass_info_varmap, proc_info).
:- mode proc_info_set_body(in, in, in, in, in, in, in, out) is det.
:- pred proc_info_declared_determinism(proc_info, maybe(determinism)).
:- mode proc_info_declared_determinism(in, out) is det.
:- pred proc_info_inferred_determinism(proc_info, determinism).
:- mode proc_info_inferred_determinism(in, out) is det.
% See also proc_info_interface_code_model in code_model.m.
:- pred proc_info_interface_determinism(proc_info, determinism).
:- mode proc_info_interface_determinism(in, out) is det.
% proc_info_never_succeeds(ProcInfo, Result):
% return Result = yes if the procedure is known to never succeed
% according to the declared determinism.
%
:- pred proc_info_never_succeeds(proc_info, bool).
:- mode proc_info_never_succeeds(in, out) is det.
:- pred proc_info_varset(proc_info, prog_varset).
:- mode proc_info_varset(in, out) is det.
:- pred proc_info_set_varset(proc_info, prog_varset, proc_info).
:- mode proc_info_set_varset(in, in, out) is det.
:- pred proc_info_vartypes(proc_info, vartypes).
:- mode proc_info_vartypes(in, out) is det.
:- pred proc_info_set_vartypes(proc_info, vartypes, proc_info).
:- mode proc_info_set_vartypes(in, in, out) is det.
:- pred proc_info_headvars(proc_info, list(prog_var)).
:- mode proc_info_headvars(in, out) is det.
:- pred proc_info_set_headvars(proc_info, list(prog_var), proc_info).
:- mode proc_info_set_headvars(in, in, out) is det.
% retreive the list of real headvars. With real headvars
% we think of those variables with which the predicate
% was initially declared (and not containing additional
% headvars that are added during the compilation process).
:- pred proc_info_real_headvars(proc_info, list(prog_var)).
:- mode proc_info_real_headvars(in, out) is det.
:- pred proc_info_argmodes(proc_info, list(mode)).
:- mode proc_info_argmodes(in, out) is det.
:- pred proc_info_set_argmodes(proc_info, list(mode), proc_info).
:- mode proc_info_set_argmodes(in, in, out) is det.
:- pred proc_info_inst_varset(proc_info, inst_varset).
:- mode proc_info_inst_varset(in, out) is det.
:- pred proc_info_set_inst_varset(proc_info, inst_varset, proc_info).
:- mode proc_info_set_inst_varset(in, in, out) is det.
:- pred proc_info_arglives(proc_info, module_info, list(is_live)).
:- mode proc_info_arglives(in, in, out) is det.
:- pred proc_info_maybe_arglives(proc_info, maybe(list(is_live))).
:- mode proc_info_maybe_arglives(in, out) is det.
:- pred proc_info_set_maybe_arglives(proc_info, maybe(list(is_live)),
proc_info).
:- mode proc_info_set_maybe_arglives(in, in, out) is det.
:- pred proc_info_goal(proc_info, hlds_goal).
:- mode proc_info_goal(in, out) is det.
:- pred proc_info_context(proc_info, prog_context).
:- mode proc_info_context(in, out) is det.
:- pred proc_info_stack_slots(proc_info, stack_slots).
:- mode proc_info_stack_slots(in, out) is det.
:- pred proc_info_liveness_info(proc_info, liveness_info).
:- mode proc_info_liveness_info(in, out) is det.
:- pred proc_info_can_process(proc_info, bool).
:- mode proc_info_can_process(in, out) is det.
:- pred proc_info_set_inferred_determinism(proc_info, determinism, proc_info).
:- mode proc_info_set_inferred_determinism(in, in, out) is det.
:- pred proc_info_set_goal(proc_info, hlds_goal, proc_info).
:- mode proc_info_set_goal(in, in, out) is det.
:- pred proc_info_arg_info(proc_info, list(arg_info)).
:- mode proc_info_arg_info(in, out) is det.
:- pred proc_info_set_arg_info(proc_info, list(arg_info), proc_info).
:- mode proc_info_set_arg_info(in, in, out) is det.
:- pred proc_info_get_initial_instmap(proc_info, module_info, instmap).
:- mode proc_info_get_initial_instmap(in, in, out) is det.
:- pred proc_info_set_liveness_info(proc_info, liveness_info, proc_info).
:- mode proc_info_set_liveness_info(in, in, out) is det.
:- pred proc_info_set_stack_slots(proc_info, stack_slots, proc_info).
:- mode proc_info_set_stack_slots(in, in, out) is det.
:- pred proc_info_get_maybe_arg_size_info(proc_info, maybe(arg_size_info)).
:- mode proc_info_get_maybe_arg_size_info(in, out) is det.
:- pred proc_info_set_maybe_arg_size_info(proc_info, maybe(arg_size_info),
proc_info).
:- mode proc_info_set_maybe_arg_size_info(in, in, out) is det.
:- pred proc_info_get_maybe_termination_info(proc_info,
maybe(termination_info)).
:- mode proc_info_get_maybe_termination_info(in, out) is det.
:- pred proc_info_set_maybe_termination_info(proc_info,
maybe(termination_info), proc_info).
:- mode proc_info_set_maybe_termination_info(in, in, out) is det.
:- pred proc_info_set_can_process(proc_info, bool, proc_info).
:- mode proc_info_set_can_process(in, in, out) is det.
:- pred proc_info_typeinfo_varmap(proc_info, type_info_varmap).
:- mode proc_info_typeinfo_varmap(in, out) is det.
:- pred proc_info_set_typeinfo_varmap(proc_info, type_info_varmap, proc_info).
:- mode proc_info_set_typeinfo_varmap(in, in, out) is det.
:- pred proc_info_eval_method(proc_info, eval_method).
:- mode proc_info_eval_method(in, out) is det.
:- pred proc_info_set_eval_method(proc_info, eval_method, proc_info).
:- mode proc_info_set_eval_method(in, in, out) is det.
:- pred proc_info_typeclass_info_varmap(proc_info, typeclass_info_varmap).
:- mode proc_info_typeclass_info_varmap(in, out) is det.
:- pred proc_info_set_typeclass_info_varmap(proc_info, typeclass_info_varmap,
proc_info).
:- mode proc_info_set_typeclass_info_varmap(in, in, out) is det.
:- pred proc_info_maybe_declared_argmodes(proc_info, maybe(list(mode))).
:- mode proc_info_maybe_declared_argmodes(in, out) is det.
:- pred proc_info_declared_argmodes(proc_info, list(mode)).
:- mode proc_info_declared_argmodes(in, out) is det.
:- pred proc_info_is_address_taken(proc_info, is_address_taken).
:- mode proc_info_is_address_taken(in, out) is det.
:- pred proc_info_set_address_taken(proc_info, is_address_taken, proc_info).
:- mode proc_info_set_address_taken(in, in, out) is det.
:- pred proc_info_get_rl_exprn_id(proc_info, maybe(rl_exprn_id)).
:- mode proc_info_get_rl_exprn_id(in, out) is det.
:- pred proc_info_set_rl_exprn_id(proc_info, rl_exprn_id, proc_info).
:- mode proc_info_set_rl_exprn_id(in, in, out) is det.
:- pred proc_info_possible_aliases(proc_info, maybe(pa_alias_as__alias_as)).
:- mode proc_info_possible_aliases(in, out) is det.
:- pred proc_info_set_possible_aliases(proc_info, alias_as, proc_info).
:- mode proc_info_set_possible_aliases(in, in, out) is det.
:- pred proc_info_global_use(proc_info, maybe(set(prog_var))).
:- mode proc_info_global_use(in, out) is det.
:- pred proc_info_set_global_use(proc_info, set(prog_var), proc_info).
:- mode proc_info_set_global_use(in, in, out) is det.
:- pred proc_info_reuse_information(proc_info,
maybe(list(sr_data__reuse_condition))).
:- mode proc_info_reuse_information(in, out) is det.
:- pred proc_info_set_reuse_information(proc_info,
maybe(list(sr_data__reuse_condition)), proc_info).
:- mode proc_info_set_reuse_information(in, in, out) is det.
:- pred proc_info_static_terms(proc_info,
maybe(list(pa_datastruct__datastruct))).
:- mode proc_info_static_terms(in, out) is det.
:- pred proc_info_set_static_terms(proc_info,
maybe(list(pa_datastruct__datastruct)), proc_info).
:- mode proc_info_set_static_terms(in, in, out) is det.
:- pred proc_info_get_need_maxfr_slot(proc_info, bool).
:- mode proc_info_get_need_maxfr_slot(in, out) is det.
:- pred proc_info_set_need_maxfr_slot(proc_info, bool, proc_info).
:- mode proc_info_set_need_maxfr_slot(in, in, out) is det.
:- pred proc_info_get_call_table_tip(proc_info, maybe(prog_var)).
:- mode proc_info_get_call_table_tip(in, out) is det.
:- pred proc_info_set_call_table_tip(proc_info, maybe(prog_var), proc_info).
:- mode proc_info_set_call_table_tip(in, in, out) is det.
% For a set of variables V, find all the type variables in the types
% of the variables in V, and return set of typeinfo variables for
% those type variables. (find all typeinfos for variables in V).
%
% This set of typeinfos is often needed in liveness computation
% for accurate garbage collection - live variables need to have
% their typeinfos stay live too.
:- pred proc_info_get_typeinfo_vars(set(prog_var), vartypes, type_info_varmap,
set(prog_var)).
:- mode proc_info_get_typeinfo_vars(in, in, in, out) is det.
:- pred proc_info_maybe_complete_with_typeinfo_vars(set(prog_var), bool,
vartypes, type_info_varmap, set(prog_var)).
:- mode proc_info_maybe_complete_with_typeinfo_vars(in, in, in, in, out)
is det.
:- pred proc_info_ensure_unique_names(proc_info, proc_info).
:- mode proc_info_ensure_unique_names(in, out) is det.
% Create a new variable of the given type to the procedure.
:- pred proc_info_create_var_from_type(proc_info, type, prog_var, proc_info).
:- mode proc_info_create_var_from_type(in, in, out, out) is det.
% Create a new variable for each element of the list of types.
:- pred proc_info_create_vars_from_types(proc_info,
list(type), list(prog_var), proc_info).
:- mode proc_info_create_vars_from_types(in, in, out, out) is det.
% Given a procedure, return a list of all its headvars which are
% (further) instantiated by the procedure.
:- pred proc_info_instantiated_head_vars(module_info, proc_info,
list(prog_var)).
:- mode proc_info_instantiated_head_vars(in, in, out) is det.
% Given a procedure, return a list of all its headvars which are
% not (further) instantiated by the procedure.
:- pred proc_info_uninstantiated_head_vars(module_info, proc_info,
list(prog_var)).
:- mode proc_info_uninstantiated_head_vars(in, in, out) is det.
% Return true if the interface of the given procedure must include
% typeinfos for all the type variables in the types of the arguments.
:- pred proc_interface_should_use_typeinfo_liveness(pred_info::in, proc_id::in,
globals::in, bool::out) is det.
% Return true if the interface of a procedure in a non-special
% predicate with the given characteristics (import/export/local
% status, address taken status) must include typeinfos for
% all the type variables in the types of the arguments.
% Note that only a few predicates in the builtin modules are special
% in this sense, and that compiler-generated predicates are never
% special.
:- pred non_special_interface_should_use_typeinfo_liveness(import_status::in,
is_address_taken::in, globals::in, bool::out) is det.
% Return true if the body of a procedure from the given predicate
% must keep a typeinfo variable alive during the lifetime of all
% variables whose type includes the corresponding type variable.
% Note that body typeinfo liveness implies interface typeinfo liveness,
% but not vice versa.
:- pred body_should_use_typeinfo_liveness(pred_info::in, globals::in,
bool::out) is det.
% Return true if the body of a procedure in a non-special predicate
% must keep a typeinfo variable alive during the lifetime of all
% variables whose type includes the corresponding type variable.
:- pred non_special_body_should_use_typeinfo_liveness(globals::in,
bool::out) is det.
% unsafe_type_cast and unsafe_promise_unique are polymorphic
% builtins which do not need their type_infos. unsafe_type_cast
% can be introduced by common.m after polymorphism is run, so it
% is much simpler to avoid introducing type_info arguments for it.
% Since both of these are really just assignment unifications, it
% is desirable to generate them inline.
% There are also some predicates in private_builtin.m to
% manipulate typeclass_infos which don't need their type_infos.
:- pred no_type_info_builtin(module_name::in, string::in, int::in) is semidet.
% If the procedure has a input/output pair of io__state arguments,
% return the positions of those arguments in the argument list.
% The positions are given as argument numbers, with the first argument
% in proc_info_headvars being position 1, and so on. The first output
% argument gives the position of the input state, the second the
% position of the output state.
%
% Note that the automatically constructed unify, index and compare
% procedures for the io:state type are not counted as having io:state
% args, since they do not fall into the scheme of one input and one
% output arg. Since they should never be called, this should not
% matter.
:- pred proc_info_has_io_state_pair(module_info::in, proc_info::in,
int::out, int::out) is semidet.
% When mode inference is enabled, we record for each inferred
% mode whether it is valid or not by keeping a list of error
% messages in the proc_info. The mode is valid iff this list
% is empty.
:- func mode_errors(proc_info) = list(mode_error_info).
:- func 'mode_errors :='(proc_info, list(mode_error_info)) = proc_info.
:- pred proc_info_is_valid_mode(proc_info::in) is semidet.
:- implementation.
:- import_module mode_errors.
:- type proc_info
---> procedure(
prog_varset :: prog_varset,
var_types :: vartypes,
real_head_vars :: list(prog_var),
% see proc_info_real_headvars/2
head_vars :: list(prog_var),
actual_head_modes :: list(mode),
mode_errors :: list(mode_error_info),
inst_varset :: inst_varset,
head_var_caller_liveness :: maybe(list(is_live)),
% Liveness (in the mode analysis sense)
% of the arguments in the caller; says
% whether each argument may be used
% after the call.
body :: hlds_goal,
proc_context :: prog_context,
% The context of the `:- mode' decl
% (or the context of the first clause,
% if there was no mode declaration).
stack_slots :: stack_slots,
% stack allocations
declared_detism :: maybe(determinism),
% _declared_ determinism
% or `no' if there was no detism decl
inferred_detism :: determinism,
can_process :: bool,
% no if we must not process this
% procedure yet (used to delay
% mode checking etc. for complicated
% modes of unification procs until
% the end of the unique_modes pass.)
arg_pass_info :: list(arg_info),
% calling convention of each arg:
% information computed by arg_info.m
% (based on the modes etc.)
% and used by code generation
% to determine how each argument
% should be passed.
initial_liveness :: liveness_info,
% the initial liveness,
% for code generation
proc_type_info_varmap :: type_info_varmap,
% typeinfo vars for type parameters
proc_typeclass_info_varmap :: typeclass_info_varmap,
% typeclass_info vars for class
% constraints
eval_method :: eval_method,
% how should the proc be evaluated
maybe_arg_sizes :: maybe(arg_size_info),
% Information about the relative sizes
% of the input and output args of the
% procedure. Set by termination
% analysis.
maybe_termination :: maybe(termination_info),
% The termination properties of the
% procedure. Set by termination
% analysis.
maybe_declared_head_modes :: maybe(list(mode)),
% declared modes of arguments.
is_address_taken :: is_address_taken,
% Is the address of this procedure
% taken? If yes, we will need to use
% typeinfo liveness for them, so that
% deep_copy and accurate gc have the
% RTTI they need for copying closures.
%
% Note that any non-local procedure
% must be considered as having its
% address taken, since it is possible
% that some other module may do so.
maybe_aditi_rl_id :: maybe(rl_exprn_id),
% For predicates with an
% `aditi_top_down' marker, which are
% executed top-down on the Aditi side
% of the connection, we generate an RL
% expression, for which this is an
% identifier. See rl_update.m.
maybe_alias_as :: maybe(alias_as),
% `Possible' aliases annotations per
% procedure. This field is set by the
% possible alias analysis.
maybe_global_use :: maybe(set(prog_var)),
% Set of headvars which are not
% fully consumed (in the sense of
% deathness as in liveness.m) in
% the procedure. This corresponds
% to the vars which are output
% w.r.t. the modes of the procedure.
% (corresponds to the final set
% of Local Forward Use in the goal)
% (set during structure_reuse phase)
% Possible set of reuse conditions.
structure_reuse:: maybe(list(sr_data__reuse_condition)),
% Possible set of datastructures that
% might be static after calling
% the procedure.
static_terms:: maybe(list(pa_datastruct__datastruct)),
need_maxfr_slot :: bool,
% True iff tracing is enabled, this
% is a procedure that lives on the det
% stack, and the code of this procedure
% may create a frame on the det stack.
% (Only in these circumstances do we
% need to reserve a stack slot to hold
% the value of maxfr at the call, for
% use in implementing retry.)
%
% This slot is used only with the LLDS
% backend XXX. Its value is set during
% the live_vars pass; it is invalid
% before then.
call_table_tip :: maybe(prog_var)
% If the tracing is enabled and the
% procedure's evaluation method is
% memo, loopcheck or minimal, this
% slot identifies the variable that
% holds the tip of the call table.
% Otherwise, this field will be set to
% `no'.
%
% Tabled procedures record, in the
% data structure identified by this
% variable, that the call is active.
% When performing a retry across
% such a procedure, we must reset
% the state of the call; if we don't,
% the retried call will find the
% active call and report an infinite
% loop error.
%
% Such resetting of course requires
% the debugger to know whether the
% procedure has reached the call table
% tip yet. Therefore when binding this
% variable, the code generator of the
% relevant backend must record this
% fact in a place accessible to the
% debugger.
).
% Some parts of the procedure aren't known yet. We initialize
% them to any old garbage which we will later throw away.
% Inferred determinism gets initialized to `erroneous'.
% This is what `det_analysis.m' wants. det_analysis.m
% will later provide the correct inferred determinism for it.
proc_info_init(Arity, Types, Modes, DeclaredModes, MaybeArgLives,
MaybeDet, MContext, IsAddressTaken, NewProc) :-
varset__init(BodyVarSet0),
make_n_fresh_vars("HeadVar__", Arity, BodyVarSet0,
HeadVars, BodyVarSet),
varset__init(InstVarSet),
map__from_corresponding_lists(HeadVars, Types, BodyTypes),
ModeErrors = [],
InferredDet = erroneous,
map__init(StackSlots),
set__init(InitialLiveness),
ArgInfo = [],
goal_info_init(GoalInfo),
ClauseBody = conj([]) - GoalInfo,
CanProcess = yes,
map__init(TVarsMap),
map__init(TCVarsMap),
RLExprn = no,
Alias = no,
GlobalUse = no,
Reuse = no,
StaticTerms = no,
NewProc = procedure(
BodyVarSet, BodyTypes, HeadVars, HeadVars,
Modes, ModeErrors, InstVarSet,
MaybeArgLives, ClauseBody, MContext, StackSlots, MaybeDet,
InferredDet, CanProcess, ArgInfo, InitialLiveness, TVarsMap,
TCVarsMap, eval_normal, no, no, DeclaredModes, IsAddressTaken,
RLExprn, Alias, GlobalUse, Reuse, StaticTerms, no, no
).
proc_info_set(DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
InstVarSet, HeadLives, Goal, Context, StackSlots,
InferredDetism, CanProcess, ArgInfo, Liveness, TVarMap,
TCVarsMap, ArgSizes, Termination, IsAddressTaken,
ProcInfo) :-
RLExprn = no,
Alias = no,
GlobalUse = no,
Reuse = no,
StaticTerms = no,
ModeErrors = [],
ProcInfo = procedure(
BodyVarSet, BodyTypes, HeadVars, HeadVars, HeadModes,
ModeErrors, InstVarSet, HeadLives, Goal, Context,
StackSlots, DeclaredDetism, InferredDetism, CanProcess, ArgInfo,
Liveness, TVarMap, TCVarsMap, eval_normal, ArgSizes,
Termination, no, IsAddressTaken, RLExprn,
Alias, GlobalUse, Reuse, StaticTerms, no, no).
proc_info_create(VarSet, VarTypes, HeadVars, HeadModes, InstVarSet, Detism,
Goal, Context, TVarMap, TCVarsMap, IsAddressTaken, ProcInfo) :-
map__init(StackSlots),
set__init(Liveness),
MaybeHeadLives = no,
RLExprn = no,
Alias = no,
GlobalUse = no,
Reuse = no,
StaticTerms = no,
ModeErrors = [],
ProcInfo = procedure(VarSet, VarTypes, HeadVars, HeadVars, HeadModes,
ModeErrors, InstVarSet,
MaybeHeadLives, Goal, Context, StackSlots,
yes(Detism), Detism, yes, [], Liveness, TVarMap, TCVarsMap,
eval_normal, no, no, no, IsAddressTaken, RLExprn,
Alias, GlobalUse, Reuse, StaticTerms, no, no).
proc_info_set_body(ProcInfo0, VarSet, VarTypes, HeadVars, Goal,
TI_VarMap, TCI_VarMap, ProcInfo) :-
ProcInfo = ((((((ProcInfo0^prog_varset := VarSet)
^var_types := VarTypes)
^head_vars := HeadVars)
^body := Goal)
^proc_type_info_varmap := TI_VarMap)
^proc_typeclass_info_varmap := TCI_VarMap).
proc_info_is_valid_mode(ProcInfo) :-
ProcInfo ^ mode_errors = [].
proc_info_interface_determinism(ProcInfo, Determinism) :-
proc_info_declared_determinism(ProcInfo, MaybeDeterminism),
(
MaybeDeterminism = no,
proc_info_inferred_determinism(ProcInfo, Determinism)
;
MaybeDeterminism = yes(Determinism)
).
% Return Result = yes if the called predicate is known to never succeed.
%
proc_info_never_succeeds(ProcInfo, Result) :-
proc_info_declared_determinism(ProcInfo, DeclaredDeterminism),
(
DeclaredDeterminism = no,
Result = no
;
DeclaredDeterminism = yes(Determinism),
determinism_components(Determinism, _, HowMany),
( HowMany = at_most_zero ->
Result = yes
;
Result = no
)
).
proc_info_arglives(ProcInfo, ModuleInfo, ArgLives) :-
proc_info_maybe_arglives(ProcInfo, MaybeArgLives),
( MaybeArgLives = yes(ArgLives0) ->
ArgLives = ArgLives0
;
proc_info_argmodes(ProcInfo, Modes),
get_arg_lives(Modes, ModuleInfo, ArgLives)
).
proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_argmodes(ProcInfo, ArgModes),
mode_list_get_initial_insts(ArgModes, ModuleInfo, InitialInsts),
assoc_list__from_corresponding_lists(HeadVars, InitialInsts, InstAL),
instmap__from_assoc_list(InstAL, InstMap).
proc_info_declared_argmodes(ProcInfo, ArgModes) :-
proc_info_maybe_declared_argmodes(ProcInfo, MaybeArgModes),
( MaybeArgModes = yes(ArgModes1) ->
ArgModes = ArgModes1
;
proc_info_argmodes(ProcInfo, ArgModes)
).
proc_info_declared_determinism(ProcInfo, ProcInfo^declared_detism).
proc_info_varset(ProcInfo, ProcInfo^prog_varset).
proc_info_vartypes(ProcInfo, ProcInfo^var_types).
proc_info_headvars(ProcInfo, ProcInfo^head_vars).
proc_info_real_headvars(ProcInfo, ProcInfo^real_head_vars).
proc_info_argmodes(ProcInfo, ProcInfo^actual_head_modes).
proc_info_inst_varset(ProcInfo, ProcInfo^inst_varset).
proc_info_maybe_arglives(ProcInfo, ProcInfo^head_var_caller_liveness).
proc_info_goal(ProcInfo, ProcInfo^body).
proc_info_context(ProcInfo, ProcInfo^proc_context).
proc_info_stack_slots(ProcInfo, ProcInfo^stack_slots).
proc_info_inferred_determinism(ProcInfo, ProcInfo^inferred_detism).
proc_info_can_process(ProcInfo, ProcInfo^can_process).
proc_info_arg_info(ProcInfo, ProcInfo^arg_pass_info).
proc_info_liveness_info(ProcInfo, ProcInfo^initial_liveness).
proc_info_typeinfo_varmap(ProcInfo, ProcInfo^proc_type_info_varmap).
proc_info_typeclass_info_varmap(ProcInfo, ProcInfo^proc_typeclass_info_varmap).
proc_info_eval_method(ProcInfo, ProcInfo^eval_method).
proc_info_get_maybe_arg_size_info(ProcInfo, ProcInfo^maybe_arg_sizes).
proc_info_get_maybe_termination_info(ProcInfo, ProcInfo^maybe_termination).
proc_info_maybe_declared_argmodes(ProcInfo, ProcInfo^maybe_declared_head_modes).
proc_info_is_address_taken(ProcInfo, ProcInfo^is_address_taken).
proc_info_get_rl_exprn_id(ProcInfo, ProcInfo^maybe_aditi_rl_id).
proc_info_possible_aliases(ProcInfo, ProcInfo^maybe_alias_as).
proc_info_global_use(ProcInfo, ProcInfo^maybe_global_use).
proc_info_reuse_information(ProcInfo, ProcInfo^structure_reuse).
proc_info_static_terms(ProcInfo, ProcInfo^static_terms).
proc_info_get_need_maxfr_slot(ProcInfo, ProcInfo^need_maxfr_slot).
proc_info_get_call_table_tip(ProcInfo, ProcInfo^call_table_tip).
proc_info_set_varset(ProcInfo, VS, ProcInfo^prog_varset := VS).
proc_info_set_vartypes(ProcInfo, VT, ProcInfo^var_types := VT).
proc_info_set_headvars(ProcInfo, HV, ProcInfo^head_vars := HV).
proc_info_set_argmodes(ProcInfo, AM, ProcInfo^actual_head_modes := AM).
proc_info_set_inst_varset(ProcInfo, IV, ProcInfo^inst_varset := IV).
proc_info_set_maybe_arglives(ProcInfo, CL,
ProcInfo^head_var_caller_liveness := CL).
proc_info_set_goal(ProcInfo, G, ProcInfo^body := G).
proc_info_set_stack_slots(ProcInfo, SS, ProcInfo^stack_slots := SS).
proc_info_set_inferred_determinism(ProcInfo, ID,
ProcInfo^inferred_detism := ID).
proc_info_set_can_process(ProcInfo, CP, ProcInfo^can_process := CP).
proc_info_set_arg_info(ProcInfo, AP, ProcInfo^arg_pass_info := AP).
proc_info_set_liveness_info(ProcInfo, IL, ProcInfo^initial_liveness := IL).
proc_info_set_typeinfo_varmap(ProcInfo, TI,
ProcInfo^proc_type_info_varmap := TI).
proc_info_set_typeclass_info_varmap(ProcInfo, TC,
ProcInfo^proc_typeclass_info_varmap := TC).
proc_info_set_eval_method(ProcInfo, EM, ProcInfo^eval_method := EM).
proc_info_set_maybe_arg_size_info(ProcInfo, MAS,
ProcInfo^maybe_arg_sizes := MAS).
proc_info_set_maybe_termination_info(ProcInfo, MT,
ProcInfo^maybe_termination := MT).
proc_info_set_address_taken(ProcInfo, AT, ProcInfo^is_address_taken := AT).
proc_info_set_rl_exprn_id(ProcInfo, ID, ProcInfo^maybe_aditi_rl_id := yes(ID)).
proc_info_set_possible_aliases(ProcInfo, Aliases,
ProcInfo^maybe_alias_as := yes(Aliases)).
proc_info_set_global_use(ProcInfo, GlobalUse,
ProcInfo^maybe_global_use := yes(GlobalUse)).
proc_info_set_reuse_information(ProcInfo, Reuse0,
ProcInfo^structure_reuse:= Reuse):-
memo_reuse_simplify(Reuse0, Reuse).
proc_info_set_static_terms(ProcInfo, StaticTerms,
ProcInfo^static_terms:= StaticTerms).
proc_info_set_need_maxfr_slot(ProcInfo, NMS, ProcInfo^need_maxfr_slot := NMS).
proc_info_set_call_table_tip(ProcInfo, CTT, ProcInfo^call_table_tip := CTT).
proc_info_get_typeinfo_vars(Vars, VarTypes, TVarMap, TypeInfoVars) :-
set__to_sorted_list(Vars, VarList),
proc_info_get_typeinfo_vars_2(VarList, VarTypes, TVarMap,
TypeInfoVarList),
set__list_to_set(TypeInfoVarList, TypeInfoVars).
% auxiliary predicate - traverses variables and builds a list of
% variables that store typeinfos for these variables.
:- pred proc_info_get_typeinfo_vars_2(list(prog_var)::in,
vartypes::in, type_info_varmap::in, list(prog_var)::out) is det.
proc_info_get_typeinfo_vars_2([], _, _, []).
proc_info_get_typeinfo_vars_2([Var | Vars], VarTypes, TVarMap, TypeInfoVars) :-
( map__search(VarTypes, Var, Type)
->
type_util__real_vars(Type, TypeVars),
(
% Optimize common case
TypeVars = []
->
proc_info_get_typeinfo_vars_2(Vars, VarTypes, TVarMap,
TypeInfoVars)
;
% XXX It's possible there are some complications with
% higher order pred types here -- if so, maybe
% treat them specially.
% The type_info is either stored in a variable,
% or in a typeclass_info. Either get the
% type_info variable or the typeclass_info
% variable
LookupVar = lambda([TVar::in, TVarVar::out] is det,
(
map__lookup(TVarMap, TVar, Locn),
type_info_locn_var(Locn, TVarVar)
)),
list__map(LookupVar, TypeVars, TypeInfoVars0),
proc_info_get_typeinfo_vars_2(Vars, VarTypes, TVarMap,
TypeInfoVars1),
list__append(TypeInfoVars0, TypeInfoVars1,
TypeInfoVars)
)
;
error("proc_info_get_typeinfo_vars_2: var not found in typemap")
).
proc_info_maybe_complete_with_typeinfo_vars(Vars0, TypeInfoLiveness,
VarTypes, TVarMap, Vars) :-
(
TypeInfoLiveness = yes,
proc_info_get_typeinfo_vars(Vars0, VarTypes, TVarMap,
TypeInfoVars),
set__union(Vars0, TypeInfoVars, Vars)
;
TypeInfoLiveness = no,
Vars = Vars0
).
proc_info_ensure_unique_names(ProcInfo0, ProcInfo) :-
proc_info_vartypes(ProcInfo0, VarTypes),
map__keys(VarTypes, AllVars),
proc_info_varset(ProcInfo0, VarSet0),
varset__ensure_unique_names(AllVars, "p", VarSet0, VarSet),
proc_info_set_varset(ProcInfo0, VarSet, ProcInfo).
proc_info_create_var_from_type(ProcInfo0, Type, NewVar, ProcInfo) :-
proc_info_varset(ProcInfo0, VarSet0),
proc_info_vartypes(ProcInfo0, VarTypes0),
varset__new_var(VarSet0, NewVar, VarSet),
map__det_insert(VarTypes0, NewVar, Type, VarTypes),
proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo).
proc_info_create_vars_from_types(ProcInfo0, Types, NewVars, ProcInfo) :-
list__length(Types, NumVars),
proc_info_varset(ProcInfo0, VarSet0),
proc_info_vartypes(ProcInfo0, VarTypes0),
varset__new_vars(VarSet0, NumVars, NewVars, VarSet),
map__det_insert_from_corresponding_lists(VarTypes0,
NewVars, Types, VarTypes),
proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo).
proc_info_instantiated_head_vars(ModuleInfo, ProcInfo, ChangedInstHeadVars) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_argmodes(ProcInfo, ArgModes),
proc_info_vartypes(ProcInfo, VarTypes),
assoc_list__from_corresponding_lists(HeadVars, ArgModes, HeadVarModes),
IsInstChanged = lambda([VarMode::in, Var::out] is semidet, (
VarMode = Var - Mode,
map__lookup(VarTypes, Var, Type),
mode_get_insts(ModuleInfo, Mode, Inst1, Inst2),
\+ inst_matches_binding(Inst1, Inst2, Type, ModuleInfo)
)),
list__filter_map(IsInstChanged, HeadVarModes, ChangedInstHeadVars).
proc_info_uninstantiated_head_vars(ModuleInfo, ProcInfo,
UnchangedInstHeadVars) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_argmodes(ProcInfo, ArgModes),
proc_info_vartypes(ProcInfo, VarTypes),
assoc_list__from_corresponding_lists(HeadVars, ArgModes, HeadVarModes),
IsInstUnchanged = lambda([VarMode::in, Var::out] is semidet, (
VarMode = Var - Mode,
map__lookup(VarTypes, Var, Type),
mode_get_insts(ModuleInfo, Mode, Inst1, Inst2),
inst_matches_binding(Inst1, Inst2, Type, ModuleInfo)
)),
list__filter_map(IsInstUnchanged, HeadVarModes, UnchangedInstHeadVars).
proc_interface_should_use_typeinfo_liveness(PredInfo, ProcId, Globals,
InterfaceTypeInfoLiveness) :-
pred_info_module(PredInfo, PredModule),
pred_info_name(PredInfo, PredName),
pred_info_arity(PredInfo, PredArity),
( no_type_info_builtin(PredModule, PredName, PredArity) ->
InterfaceTypeInfoLiveness = no
;
pred_info_import_status(PredInfo, Status),
pred_info_procedures(PredInfo, ProcTable),
map__lookup(ProcTable, ProcId, ProcInfo),
proc_info_is_address_taken(ProcInfo, IsAddressTaken),
non_special_interface_should_use_typeinfo_liveness(Status,
IsAddressTaken, Globals, InterfaceTypeInfoLiveness)
).
non_special_interface_should_use_typeinfo_liveness(Status, IsAddressTaken,
Globals, InterfaceTypeInfoLiveness) :-
(
(
IsAddressTaken = address_is_taken
;
% If the predicate is exported, its address may have
% been taken elsewhere. If it is imported, then it
% follows that it must be exported somewhere.
Status \= local
;
non_special_body_should_use_typeinfo_liveness(Globals,
yes)
)
->
InterfaceTypeInfoLiveness = yes
;
InterfaceTypeInfoLiveness = no
).
body_should_use_typeinfo_liveness(PredInfo, Globals, BodyTypeInfoLiveness) :-
pred_info_module(PredInfo, PredModule),
pred_info_name(PredInfo, PredName),
pred_info_arity(PredInfo, PredArity),
( no_type_info_builtin(PredModule, PredName, PredArity) ->
BodyTypeInfoLiveness = no
;
non_special_body_should_use_typeinfo_liveness(Globals,
BodyTypeInfoLiveness)
).
non_special_body_should_use_typeinfo_liveness(Globals, BodyTypeInfoLiveness) :-
globals__lookup_bool_option(Globals, body_typeinfo_liveness,
BodyTypeInfoLiveness).
no_type_info_builtin(ModuleName, PredName, Arity) :-
no_type_info_builtin_2(ModuleNameType, PredName, Arity),
(
ModuleNameType = builtin,
mercury_public_builtin_module(ModuleName)
;
ModuleNameType = private_builtin,
mercury_private_builtin_module(ModuleName)
;
ModuleNameType = table_builtin,
mercury_table_builtin_module(ModuleName)
).
:- type builtin_mod ---> builtin ; private_builtin ; table_builtin.
:- pred no_type_info_builtin_2(builtin_mod::out, string::in, int::in)
is semidet.
no_type_info_builtin_2(private_builtin, "unsafe_type_cast", 2).
no_type_info_builtin_2(builtin, "unsafe_promise_unique", 2).
no_type_info_builtin_2(private_builtin, "superclass_from_typeclass_info", 3).
no_type_info_builtin_2(private_builtin,
"instance_constraint_from_typeclass_info", 3).
no_type_info_builtin_2(private_builtin, "type_info_from_typeclass_info", 3).
no_type_info_builtin_2(private_builtin,
"unconstrained_type_info_from_typeclass_info", 3).
no_type_info_builtin_2(table_builtin, "table_restore_any_ans", 3).
no_type_info_builtin_2(table_builtin, "table_lookup_insert_enum", 4).
proc_info_has_io_state_pair(ModuleInfo, ProcInfo, InArgNum, OutArgNum) :-
proc_info_headvars(ProcInfo, HeadVars),
proc_info_argmodes(ProcInfo, ArgModes),
assoc_list__from_corresponding_lists(HeadVars, ArgModes,
HeadVarsModes),
proc_info_vartypes(ProcInfo, VarTypes),
proc_info_has_io_state_pair_2(HeadVarsModes, ModuleInfo, VarTypes,
1, no, no, MaybeIn, MaybeOut),
( MaybeIn = yes(In), MaybeOut = yes(Out) ->
InArgNum = In,
OutArgNum = Out
;
fail
).
:- pred proc_info_has_io_state_pair_2(assoc_list(prog_var, mode)::in,
module_info::in, map(prog_var, type)::in,
int::in, maybe(int)::in, maybe(int)::in,
maybe(int)::out, maybe(int)::out) is semidet.
proc_info_has_io_state_pair_2([], _, _, _,
MaybeIn, MaybeOut, MaybeIn, MaybeOut).
proc_info_has_io_state_pair_2([Var - Mode | VarModes], ModuleInfo, VarTypes,
ArgNum, MaybeIn0, MaybeOut0, MaybeIn, MaybeOut) :-
(
map__lookup(VarTypes, Var, VarType),
type_util__type_is_io_state(VarType)
->
( mode_is_fully_input(ModuleInfo, Mode) ->
(
MaybeIn0 = no,
MaybeIn1 = yes(ArgNum),
MaybeOut1 = MaybeOut0
;
MaybeIn0 = yes(_),
% Procedures with two input arguments
% of type io__state (e.g. the automatically
% generated unification or comparison procedure
% for the io__state type) do not fall into
% the one input/one output pattern we are
% looking for.
fail
)
; mode_is_fully_output(ModuleInfo, Mode) ->
(
MaybeOut0 = no,
MaybeOut1 = yes(ArgNum),
MaybeIn1 = MaybeIn0
;
MaybeOut0 = yes(_),
% Procedures with two output arguments of
% type io__state do not fall into the one
% input/one output pattern we are looking for.
fail
)
;
fail
)
;
MaybeIn1 = MaybeIn0,
MaybeOut1 = MaybeOut0
),
proc_info_has_io_state_pair_2(VarModes, ModuleInfo, VarTypes,
ArgNum + 1, MaybeIn1, MaybeOut1, MaybeIn, MaybeOut).
%-----------------------------------------------------------------------------%
:- interface.
% make_n_fresh_vars(Name, N, VarSet0, Vars, VarSet):
% `Vars' is a list of `N' fresh variables allocated from
% `VarSet0'. The variables will be named "<Name>1", "<Name>2",
% "<Name>3", and so on, where <Name> is the value of `Name'.
% `VarSet' is the resulting varset.
:- pred make_n_fresh_vars(string, int, varset(T), list(var(T)), varset(T)).
:- mode make_n_fresh_vars(in, in, in, out, out) is det.
% given the list of predicate arguments for a predicate that
% is really a function, split that list into the function arguments
% and the function return type.
:- pred pred_args_to_func_args(list(T), list(T), T).
:- mode pred_args_to_func_args(in, out, out) is det.
% adjust_func_arity(PredOrFunc, FuncArity, PredArity).
%
% We internally store the arity as the length of the argument
% list including the return value, which is one more than the
% arity of the function reported in error messages.
:- pred adjust_func_arity(pred_or_func, int, int).
:- mode adjust_func_arity(in, in, out) is det.
:- mode adjust_func_arity(in, out, in) is det.
% Get the last two arguments from the list, failing if there
% aren't at least two arguments.
:- pred get_state_args(list(T), list(T), T, T).
:- mode get_state_args(in, out, out, out) is semidet.
% Get the last two arguments from the list, aborting if there
% aren't at least two arguments.
:- pred get_state_args_det(list(T), list(T), T, T).
:- mode get_state_args_det(in, out, out, out) is det.
:- implementation.
make_n_fresh_vars(BaseName, N, VarSet0, Vars, VarSet) :-
make_n_fresh_vars_2(BaseName, 0, N, VarSet0, Vars, VarSet).
:- pred make_n_fresh_vars_2(string, int, int, varset(T), list(var(T)),
varset(T)).
:- mode make_n_fresh_vars_2(in, in, in, in, out, out) is det.
make_n_fresh_vars_2(BaseName, N, Max, VarSet0, Vars, VarSet) :-
(N = Max ->
VarSet = VarSet0,
Vars = []
;
N1 is N + 1,
varset__new_var(VarSet0, Var, VarSet1),
string__int_to_string(N1, Num),
string__append(BaseName, Num, VarName),
varset__name_var(VarSet1, Var, VarName, VarSet2),
Vars = [Var | Vars1],
make_n_fresh_vars_2(BaseName, N1, Max, VarSet2, Vars1, VarSet)
).
pred_args_to_func_args(PredArgs, FuncArgs, FuncReturn) :-
list__length(PredArgs, NumPredArgs),
NumFuncArgs is NumPredArgs - 1,
( list__split_list(NumFuncArgs, PredArgs, FuncArgs0, [FuncReturn0]) ->
FuncArgs = FuncArgs0,
FuncReturn = FuncReturn0
;
error("pred_args_to_func_args: function missing return value?")
).
adjust_func_arity(predicate, Arity, Arity).
adjust_func_arity(function, Arity - 1, Arity).
get_state_args(Args0, Args, State0, State) :-
list__reverse(Args0, RevArgs0),
RevArgs0 = [State, State0 | RevArgs],
list__reverse(RevArgs, Args).
get_state_args_det(Args0, Args, State0, State) :-
( get_state_args(Args0, Args1, State0A, StateA) ->
Args = Args1,
State0 = State0A,
State = StateA
;
error("hlds_pred__get_state_args_det")
).
%-----------------------------------------------------------------------------%
% Predicates to deal with record syntax.
:- interface.
% field_extraction_function_args(Args, InputTermArg).
% Work out which arguments of a field access correspond to the
% field being extracted/set, and which are the container arguments.
:- pred field_extraction_function_args(list(prog_var), prog_var).
:- mode field_extraction_function_args(in, out) is det.
% field_update_function_args(Args, InputTermArg, FieldArg).
:- pred field_update_function_args(list(prog_var), prog_var, prog_var).
:- mode field_update_function_args(in, out, out) is det.
% field_access_function_name(AccessType, FieldName, FuncName).
%
% From the access type and the name of the field,
% construct a function name.
:- pred field_access_function_name(field_access_type,
ctor_field_name, sym_name).
:- mode field_access_function_name(in, in, out) is det.
% is_field_access_function_name(ModuleInfo, FuncName, Arity,
% AccessType, FieldName).
%
% Inverse of the above.
:- pred is_field_access_function_name(module_info, sym_name, arity,
field_access_type, ctor_field_name).
:- mode is_field_access_function_name(in, in, out, out, out) is semidet.
:- pred pred_info_is_field_access_function(module_info, pred_info).
:- mode pred_info_is_field_access_function(in, in) is semidet.
:- implementation.
field_extraction_function_args(Args, TermInputArg) :-
( Args = [TermInputArg0] ->
TermInputArg = TermInputArg0
;
error("field_extraction_function_args")
).
field_update_function_args(Args, TermInputArg, FieldArg) :-
( Args = [TermInputArg0, FieldArg0] ->
FieldArg = FieldArg0,
TermInputArg = TermInputArg0
;
error("field_update_function_args")
).
field_access_function_name(get, FieldName, FieldName).
field_access_function_name(set, FieldName, FuncName) :-
add_sym_name_suffix(FieldName, " :=", FuncName).
is_field_access_function_name(ModuleInfo, FuncName, Arity,
AccessType, FieldName) :-
( remove_sym_name_suffix(FuncName, " :=", FieldName0) ->
Arity = 2,
AccessType = set,
FieldName = FieldName0
;
Arity = 1,
AccessType = get,
FieldName = FuncName
),
module_info_ctor_field_table(ModuleInfo, CtorFieldTable),
map__contains(CtorFieldTable, FieldName).
pred_info_is_field_access_function(ModuleInfo, PredInfo) :-
pred_info_get_is_pred_or_func(PredInfo, function),
pred_info_module(PredInfo, Module),
pred_info_name(PredInfo, Name),
pred_info_arity(PredInfo, PredArity),
adjust_func_arity(function, FuncArity, PredArity),
is_field_access_function_name(ModuleInfo, qualified(Module, Name),
FuncArity, _, _).
%-----------------------------------------------------------------------------%
% Predicates to check whether a given predicate
% is an Aditi query.
:- interface.
:- pred hlds_pred__is_base_relation(module_info, pred_id).
:- mode hlds_pred__is_base_relation(in, in) is semidet.
:- pred hlds_pred__is_derived_relation(module_info, pred_id).
:- mode hlds_pred__is_derived_relation(in, in) is semidet.
% Is the given predicate a base or derived Aditi relation.
:- pred hlds_pred__is_aditi_relation(module_info, pred_id).
:- mode hlds_pred__is_aditi_relation(in, in) is semidet.
% Is the predicate `aditi:aggregate_compute_initial', declared
% in extras/aditi/aditi.m.
% Special code is generated for each call to this in rl_gen.m.
:- pred hlds_pred__is_aditi_aggregate(module_info, pred_id).
:- mode hlds_pred__is_aditi_aggregate(in, in) is semidet.
:- pred hlds_pred__pred_info_is_aditi_relation(pred_info).
:- mode hlds_pred__pred_info_is_aditi_relation(in) is semidet.
:- pred hlds_pred__pred_info_is_aditi_aggregate(pred_info).
:- mode hlds_pred__pred_info_is_aditi_aggregate(in) is semidet.
:- pred hlds_pred__pred_info_is_base_relation(pred_info).
:- mode hlds_pred__pred_info_is_base_relation(in) is semidet.
% Aditi can optionally memo the results of predicates
% between calls to reduce redundant computation.
:- pred hlds_pred__is_aditi_memoed(module_info, pred_id).
:- mode hlds_pred__is_aditi_memoed(in, in) is semidet.
% Differential evaluation is a method of evaluating recursive
% Aditi predicates which uses the just new tuples in each
% iteration where possible rather than the full relations,
% reducing the sizes of joins.
:- pred hlds_pred__is_differential(module_info, pred_id).
:- mode hlds_pred__is_differential(in, in) is semidet.
%-----------------------------------------------------------------------------%
:- implementation.
hlds_pred__is_base_relation(ModuleInfo, PredId) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
hlds_pred__pred_info_is_base_relation(PredInfo).
hlds_pred__pred_info_is_base_relation(PredInfo) :-
pred_info_get_markers(PredInfo, Markers),
check_marker(Markers, base_relation).
hlds_pred__is_derived_relation(ModuleInfo, PredId) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
pred_info_get_markers(PredInfo, Markers),
check_marker(Markers, aditi),
\+ hlds_pred__pred_info_is_base_relation(PredInfo),
\+ hlds_pred__pred_info_is_aditi_aggregate(PredInfo).
hlds_pred__is_aditi_relation(ModuleInfo, PredId) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
hlds_pred__pred_info_is_aditi_relation(PredInfo).
hlds_pred__pred_info_is_aditi_relation(PredInfo) :-
pred_info_get_markers(PredInfo, Markers),
check_marker(Markers, aditi).
hlds_pred__is_aditi_aggregate(ModuleInfo, PredId) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
hlds_pred__pred_info_is_aditi_aggregate(PredInfo).
hlds_pred__pred_info_is_aditi_aggregate(PredInfo) :-
pred_info_module(PredInfo, Module),
pred_info_name(PredInfo, Name),
pred_info_arity(PredInfo, Arity),
hlds_pred__aditi_aggregate(Module, Name, Arity).
:- pred hlds_pred__aditi_aggregate(sym_name, string, int).
:- mode hlds_pred__aditi_aggregate(in, in, in) is semidet.
hlds_pred__aditi_aggregate(unqualified("aditi"),
"aggregate_compute_initial", 5).
hlds_pred__is_aditi_memoed(ModuleInfo, PredId) :-
% XXX memoing doesn't work yet.
semidet_fail,
module_info_pred_info(ModuleInfo, PredId, PredInfo),
pred_info_get_markers(PredInfo, Markers),
(
check_marker(Markers, aditi_memo)
;
% Memoing is the default for Aditi procedures.
semidet_fail, % XXX leave it off for now to
% reduce memory usage.
check_marker(Markers, aditi),
\+ check_marker(Markers, aditi_no_memo)
).
hlds_pred__is_differential(ModuleInfo, PredId) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
pred_info_get_markers(PredInfo, Markers),
(
check_marker(Markers, psn)
;
% Predicate semi-naive evaluation is the default.
check_marker(Markers, aditi),
\+ check_marker(Markers, naive)
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- interface.
% Check if the given evaluation method is allowed with
% the given determinism.
:- pred valid_determinism_for_eval_method(eval_method, determinism).
:- mode valid_determinism_for_eval_method(in, in) is semidet.
% Convert an evaluation method to a string.
:- pred eval_method_to_string(eval_method, string).
:- mode eval_method_to_string(in, out) is det.
% Return true if the given evaluation method requires a
% stratification check.
:- func eval_method_needs_stratification(eval_method) = bool.
% Return true if the given evaluation method uses a per-procedure
% tabling pointer. If so, the back-end must generate a declaration
% for the variable to hold the table.
:- func eval_method_has_per_proc_tabling_pointer(eval_method) = bool.
% Return true if the given evaluation method requires the body
% of the procedure using it to be transformed by table_gen.m.
:- func eval_method_requires_tabling_transform(eval_method) = bool.
% Return true if the given evaluation method requires the arguments
% of the procedure using it to be ground.
:- func eval_method_requires_ground_args(eval_method) = bool.
% Return true if the given evaluation method requires the arguments
% of the procedure using it to be non-unique.
:- func eval_method_destroys_uniqueness(eval_method) = bool.
% Return the change a given evaluation method can do to a given
% determinism.
:- pred eval_method_change_determinism(eval_method, determinism,
determinism).
:- mode eval_method_change_determinism(in, in, out) is det.
:- implementation.
:- import_module det_analysis.
valid_determinism_for_eval_method(eval_normal, _).
valid_determinism_for_eval_method(eval_loop_check, _).
valid_determinism_for_eval_method(eval_table_io, _) :-
error("valid_determinism_for_eval_method called after tabling phase").
valid_determinism_for_eval_method(eval_memo, _).
valid_determinism_for_eval_method(eval_minimal, Determinism) :-
determinism_components(Determinism, can_fail, _).
eval_method_to_string(eval_normal, "normal").
eval_method_to_string(eval_loop_check, "loop_check").
eval_method_to_string(eval_table_io, "table_io").
eval_method_to_string(eval_memo, "memo").
eval_method_to_string(eval_minimal, "minimal_model").
eval_method_needs_stratification(eval_normal) = no.
eval_method_needs_stratification(eval_loop_check) = no.
eval_method_needs_stratification(eval_table_io) = no.
eval_method_needs_stratification(eval_memo) = no.
eval_method_needs_stratification(eval_minimal) = yes.
eval_method_has_per_proc_tabling_pointer(eval_normal) = no.
eval_method_has_per_proc_tabling_pointer(eval_loop_check) = yes.
eval_method_has_per_proc_tabling_pointer(eval_table_io) = no.
eval_method_has_per_proc_tabling_pointer(eval_memo) = yes.
eval_method_has_per_proc_tabling_pointer(eval_minimal) = yes.
eval_method_requires_tabling_transform(eval_normal) = no.
eval_method_requires_tabling_transform(eval_loop_check) = yes.
eval_method_requires_tabling_transform(eval_table_io) = yes.
eval_method_requires_tabling_transform(eval_memo) = yes.
eval_method_requires_tabling_transform(eval_minimal) = yes.
eval_method_requires_ground_args(eval_normal) = no.
eval_method_requires_ground_args(eval_loop_check) = yes.
eval_method_requires_ground_args(eval_table_io) = yes.
eval_method_requires_ground_args(eval_memo) = yes.
eval_method_requires_ground_args(eval_minimal) = yes.
eval_method_destroys_uniqueness(eval_normal) = no.
eval_method_destroys_uniqueness(eval_loop_check) = yes.
eval_method_destroys_uniqueness(eval_table_io) = no.
eval_method_destroys_uniqueness(eval_memo) = yes.
eval_method_destroys_uniqueness(eval_minimal) = yes.
eval_method_change_determinism(eval_normal, Detism, Detism).
eval_method_change_determinism(eval_loop_check, Detism, Detism).
eval_method_change_determinism(eval_table_io, Detism, Detism).
eval_method_change_determinism(eval_memo, Detism, Detism).
eval_method_change_determinism(eval_minimal, Det0, Det) :-
det_conjunction_detism(semidet, Det0, Det).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
More information about the developers
mailing list