Files
mercury/compiler/simplify_goal_unify.m
Zoltan Somogyi 07f877bc3f Carve term_context.m out of term.m.
library/term.m:
library/term_context.m:
    As above.

    Rename the term.context type as term_context.term_context, with
    term.context now being defined as an equivalence type.

    Replace the context_init function and predicate and the dummy_context_init
    function with just one function: dummy_context. This name includes
    the important part (the fact that it return a *dummy* context) and deletes
    the nonimportant part (dummy contexts are just about never updated,
    so the function does not really "initialize" them).

    Reduce function/predicate pairs that do the same thing to just a function.

library/MODULES_DOC:
library/library.m:
    Add the new module to the list of standard library modules.

NEWS:
    Mention the new module, and the obsoleting of the moved predicates
    and functions in term.m.

compiler/*.m:
library/*.m:
    Conform to the changes above.
2022-08-23 12:56:37 +10:00

346 lines
15 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2014 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: simplify_goal_unify.m.
%
% This module handles simplification of unifications.
%
%---------------------------------------------------------------------------%
:- module check_hlds.simplify.simplify_goal_unify.
:- interface.
:- import_module check_hlds.simplify.common.
:- import_module check_hlds.simplify.simplify_info.
:- import_module hlds.
:- import_module hlds.hlds_goal.
:- import_module hlds.instmap.
:- pred simplify_goal_unify(
hlds_goal_expr::in(goal_expr_unify), hlds_goal_expr::out,
hlds_goal_info::in, hlds_goal_info::out,
simplify_nested_context::in, instmap::in,
common_info::in, common_info::out,
simplify_info::in, simplify_info::out) is det.
%---------------------------------------------------------------------------%
:- implementation.
:- import_module check_hlds.polymorphism_type_info.
:- import_module check_hlds.proc_requests.
:- import_module check_hlds.simplify.simplify_goal.
:- import_module check_hlds.type_util.
:- import_module hlds.code_model.
:- import_module hlds.goal_util.
:- import_module hlds.hlds_module.
:- import_module hlds.hlds_pred.
:- import_module hlds.hlds_rtti.
:- import_module hlds.make_goal.
:- import_module hlds.pred_table.
:- import_module hlds.special_pred.
:- import_module mdbcomp.
:- import_module mdbcomp.builtin_modules.
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_type.
:- import_module parse_tree.set_of_var.
:- import_module parse_tree.var_table.
:- import_module bool.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module require.
:- import_module term_context.
:- import_module uint.
simplify_goal_unify(GoalExpr0, GoalExpr, GoalInfo0, GoalInfo,
NestedContext0, InstMap0, !Common, !Info) :-
GoalExpr0 = unify(LHSVar0, RHS0, UnifyMode, Unification0, UnifyContext),
(
RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
NonLocals, VarsModes, LambdaDeclaredDetism, LambdaGoal0),
determinism_to_code_model(LambdaDeclaredDetism, LambdaCodeModel),
(
( LambdaCodeModel = model_det
; LambdaCodeModel = model_semi
),
LambdaProcIsModelNon = no
;
LambdaCodeModel = model_non,
Context = goal_info_get_context(GoalInfo0),
LambdaProcIsModelNon = yes(imp_lambda(Context))
),
NestedContext0 = simplify_nested_context(InsideDuplForSwitch,
_ProcModelNon, NumEnclosingBarriers),
( if goal_info_has_feature(GoalInfo0, feature_lambda_from_try) then
LambdaNumEnclosingBarriers = NumEnclosingBarriers
else
LambdaNumEnclosingBarriers = NumEnclosingBarriers + 1u
),
LambdaNestedContext = simplify_nested_context(InsideDuplForSwitch,
LambdaProcIsModelNon, LambdaNumEnclosingBarriers),
simplify_info_get_module_info(!.Info, ModuleInfo),
instmap.pre_lambda_update(ModuleInfo, VarsModes,
InstMap0, LambdaInstMap0),
% Don't attempt to pass structs into lambda_goals, since that
% could change the curried non-locals of the lambda_goal, and
% that would be difficult to fix up.
simplify_info_get_simplify_tasks(!.Info, SimplifyTasks),
LambdaCommon0 = common_info_init(SimplifyTasks),
% Don't attempt to pass structs out of lambda_goals.
simplify_goal(LambdaGoal0, LambdaGoal, LambdaNestedContext,
LambdaInstMap0, LambdaCommon0, _, !Info),
RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
NonLocals, VarsModes, LambdaDeclaredDetism, LambdaGoal),
GoalExpr = unify(LHSVar0, RHS, UnifyMode, Unification0, UnifyContext),
GoalInfo = GoalInfo0
;
( RHS0 = rhs_functor(_, _, _)
; RHS0 = rhs_var(_)
),
( if
% A unification of the form X = X can be safely optimised away.
RHS0 = rhs_var(LHSVar0)
then
Context = goal_info_get_context(GoalInfo0),
hlds_goal(GoalExpr, GoalInfo) = true_goal_with_context(Context)
else if
Unification0 = complicated_unify(ComplMode, CanFail, TypeInfoVars)
then
(
RHS0 = rhs_var(V),
process_compl_unify(LHSVar0, V, ComplMode, CanFail,
TypeInfoVars, UnifyContext, GoalInfo0, GoalExpr1,
NestedContext0, InstMap0, !Common, !Info),
GoalExpr1 = hlds_goal(GoalExpr, GoalInfo)
;
RHS0 = rhs_functor(_, _, _),
unexpected($pred, "invalid RHS for complicated unify")
)
else
common_optimise_unification(RHS0, UnifyMode, Unification0,
UnifyContext, GoalExpr0, GoalExpr, GoalInfo0, GoalInfo,
!Common, !Info)
)
).
:- pred process_compl_unify(prog_var::in, prog_var::in, unify_mode::in,
can_fail::in, list(prog_var)::in, unify_context::in, hlds_goal_info::in,
hlds_goal::out, simplify_nested_context::in, instmap::in,
common_info::in, common_info::out,
simplify_info::in, simplify_info::out) is det.
process_compl_unify(XVar, YVar, UnifyMode, CanFail, _OldTypeInfoVars,
UnifyContext, GoalInfo0, Goal, NestedContext0, InstMap0,
!Common, !Info) :-
simplify_info_get_module_info(!.Info, ModuleInfo),
simplify_info_get_var_table(!.Info, VarTable),
lookup_var_type(VarTable, XVar, Type),
( if Type = type_variable(TypeVar, Kind) then
% Convert polymorphic unifications into calls to `unify/2',
% the general unification predicate, passing the appropriate type_info:
% unify(TypeInfoVar, X, Y)
% where TypeInfoVar is the type_info variable associated with
% the type of the variables that are being unified.
Context = goal_info_get_context(GoalInfo0),
get_type_info_locn(TypeVar, Kind, Context, TypeInfoVar, ExtraGoals,
!Info),
call_generic_unify(TypeInfoVar, XVar, YVar, ModuleInfo, !.Info,
UnifyContext, GoalInfo0, Call)
else if type_is_higher_order(Type) then
% Convert higher-order unifications into calls to
% builtin_unify_pred (which calls error/1).
Context = goal_info_get_context(GoalInfo0),
generate_plain_call(ModuleInfo, pf_predicate,
mercury_private_builtin_module, "builtin_unify_pred",
[], [XVar, YVar], instmap_delta_bind_no_var, mode_no(0),
detism_semi, purity_pure, [], Context, hlds_goal(Call0, _)),
simplify_goal_expr(Call0, Call1, GoalInfo0, GoalInfo,
NestedContext0, InstMap0, !Common, !Info),
Call = hlds_goal(Call1, GoalInfo),
ExtraGoals = []
else
type_to_ctor_and_args_det(Type, TypeCtor, TypeArgs),
determinism_components(Detism, CanFail, at_most_one),
lookup_mode_num(ModuleInfo, TypeCtor, UnifyMode, Detism, ProcId),
( if
% On the Erlang backend, it was faster for us to use builtin
% comparison operators on high level data structures than to
% deconstruct the data structure and compare the atomic
% constituents. We can only do this on values of a type
% if that type does not have user-defined equality.
%
% The Erlang backend was the only one on which
% can_compare_compound_values could ever be "yes".
%
% globals.lookup_bool_option(Globals,
% can_compare_compound_values, yes),
semidet_fail,
hlds_pred.in_in_unification_proc_id(ProcId),
type_definitely_has_no_user_defined_equality_pred(ModuleInfo, Type)
then
ExtraGoals = [],
Context = goal_info_get_context(GoalInfo0),
generate_plain_call(ModuleInfo, pf_predicate,
mercury_private_builtin_module, "builtin_compound_eq",
[], [XVar, YVar], instmap_delta_bind_no_var, only_mode,
detism_semi, purity_pure, [], Context, Call)
else if
hlds_pred.in_in_unification_proc_id(ProcId),
% For most imported types, we only generate unification
% predicate declarations if they are needed for complicated
% unifications other than proc_id 0. higher_order.m will
% specialize these cases if possible.
special_pred_is_generated_lazily(ModuleInfo, TypeCtor)
then
make_type_info_vars([Type], TypeInfoVars, ExtraGoals, !Info),
( if TypeInfoVars = [TypeInfoVarPrime] then
TypeInfoVar = TypeInfoVarPrime
else
unexpected($pred, "more than one typeinfo for one type var")
),
call_generic_unify(TypeInfoVar, XVar, YVar, ModuleInfo, !.Info,
UnifyContext, GoalInfo0, Call)
else
% Convert other complicated unifications into calls to
% specific unification predicates, inserting extra typeinfo
% arguments if necessary.
make_type_info_vars(TypeArgs, TypeInfoVars, ExtraGoals, !Info),
call_specific_unify(TypeCtor, TypeInfoVars, XVar, YVar, ProcId,
ModuleInfo, UnifyContext, GoalInfo0, Call0, CallGoalInfo0),
simplify_goal_expr(Call0, Call1, CallGoalInfo0, CallGoalInfo1,
NestedContext0, InstMap0, !Common, !Info),
Call = hlds_goal(Call1, CallGoalInfo1)
)
),
Conjuncts = ExtraGoals ++ [Call],
conj_list_to_goal(Conjuncts, GoalInfo0, Goal).
:- pred call_generic_unify(prog_var::in, prog_var::in, prog_var::in,
module_info::in, simplify_info::in, unify_context::in,
hlds_goal_info::in, hlds_goal::out) is det.
call_generic_unify(TypeInfoVar, XVar, YVar, ModuleInfo, _, _, GoalInfo,
Call) :-
Context = goal_info_get_context(GoalInfo),
generate_plain_call(ModuleInfo, pf_predicate,
mercury_public_builtin_module, "unify",
[TypeInfoVar], [XVar, YVar], instmap_delta_bind_no_var, mode_no(0),
detism_semi, purity_pure, [], Context, Call).
:- pred call_specific_unify(type_ctor::in, list(prog_var)::in,
prog_var::in, prog_var::in, proc_id::in,
module_info::in, unify_context::in, hlds_goal_info::in,
hlds_goal_expr::out, hlds_goal_info::out) is det.
call_specific_unify(TypeCtor, TypeInfoVars, XVar, YVar, ProcId, ModuleInfo,
Context, GoalInfo0, CallExpr, CallGoalInfo) :-
% Create the new call goal.
ArgVars = TypeInfoVars ++ [XVar, YVar],
module_info_get_special_pred_maps(ModuleInfo, SpecialPredMaps),
UnifyMap = SpecialPredMaps ^ spm_unify_map,
map.lookup(UnifyMap, TypeCtor, PredId),
module_info_pred_info(ModuleInfo, PredId, PredInfo),
ModuleName = pred_info_module(PredInfo),
PredName = pred_info_name(PredInfo),
SymName = qualified(ModuleName, PredName),
CallContext = call_unify_context(XVar, rhs_var(YVar), Context),
CallExpr = plain_call(PredId, ProcId, ArgVars, not_builtin,
yes(CallContext), SymName),
% Add the extra type_info vars to the nonlocals for the call.
NonLocals0 = goal_info_get_nonlocals(GoalInfo0),
set_of_var.insert_list(TypeInfoVars, NonLocals0, NonLocals),
goal_info_set_nonlocals(NonLocals, GoalInfo0, CallGoalInfo).
%---------------------------------------------------------------------------%
:- pred make_type_info_vars(list(mer_type)::in, list(prog_var)::out,
list(hlds_goal)::out, simplify_info::in, simplify_info::out) is det.
make_type_info_vars(Types, TypeInfoVars, TypeInfoGoals, !Info) :-
% Extract the information from simplify_info.
simplify_info_get_var_table(!.Info, VarTable0),
simplify_info_get_rtti_varmaps(!.Info, RttiVarMaps0),
simplify_info_get_module_info(!.Info, ModuleInfo0),
simplify_info_get_pred_proc_id(!.Info, PredProcId),
some [!PredInfo, !ProcInfo] (
% The varset, var_table and rtti_varmaps get updated by the call to
% polymorphism_make_type_info_vars_raw_store below, which will get
% this information from the pred_info and proc_info.
module_info_pred_proc_info(ModuleInfo0, PredProcId,
!:PredInfo, !:ProcInfo),
proc_info_set_var_table(VarTable0, !ProcInfo),
proc_info_set_rtti_varmaps(RttiVarMaps0, !ProcInfo),
% Generate the code that creates the type_infos.
polymorphism_make_type_info_vars_mi(Types, dummy_context,
TypeInfoVars, TypeInfoGoals, ModuleInfo0, ModuleInfo1,
!PredInfo, !ProcInfo),
proc_info_get_var_table(!.ProcInfo, VarTable),
proc_info_get_rtti_varmaps(!.ProcInfo, RttiVarMaps),
simplify_info_set_var_table(VarTable, !Info),
simplify_info_set_rtti_varmaps(RttiVarMaps, !Info),
% Put the new proc_info and pred_info back in the module_info
% and put the new module_info back in the simplify_info.
module_info_set_pred_proc_info(PredProcId, !.PredInfo, !.ProcInfo,
ModuleInfo1, ModuleInfo),
simplify_info_set_module_info(ModuleInfo, !Info)
).
:- pred get_type_info_locn(tvar::in, kind::in, prog_context::in, prog_var::out,
list(hlds_goal)::out, simplify_info::in, simplify_info::out) is det.
get_type_info_locn(TypeVar, Kind, Context, TypeInfoVar, Goals, !Info) :-
simplify_info_get_rtti_varmaps(!.Info, RttiVarMaps),
rtti_lookup_type_info_locn(RttiVarMaps, TypeVar, TypeInfoLocn),
(
% If the typeinfo is available in a variable, just use it.
TypeInfoLocn = type_info(TypeInfoVar),
Goals = []
;
% If the typeinfo is in a typeclass_info then we need to extract it.
TypeInfoLocn = typeclass_info(TypeClassInfoVar, Index),
extract_type_info(TypeVar, Kind, TypeClassInfoVar, Index, Context,
Goals, TypeInfoVar, !Info)
).
:- pred extract_type_info(tvar::in, kind::in, prog_var::in, int::in,
prog_context::in, list(hlds_goal)::out, prog_var::out,
simplify_info::in, simplify_info::out) is det.
extract_type_info(TypeVar, Kind, TypeClassInfoVar, Index, Context,
Goals, TypeInfoVar, !Info) :-
simplify_info_get_module_info(!.Info, ModuleInfo),
simplify_info_get_var_table(!.Info, VarTable0),
simplify_info_get_rtti_varmaps(!.Info, RttiVarMaps0),
polymorphism_type_info.gen_extract_type_info(ModuleInfo, TypeVar, Kind,
TypeClassInfoVar, iov_int(Index), Context, Goals, TypeInfoVar,
VarTable0, VarTable, RttiVarMaps0, RttiVarMaps),
simplify_info_set_var_table(VarTable, !Info),
simplify_info_set_rtti_varmaps(RttiVarMaps, !Info).
%---------------------------------------------------------------------------%
:- end_module check_hlds.simplify.simplify_goal_unify.
%---------------------------------------------------------------------------%