mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
386 lines
16 KiB
Mathematica
386 lines
16 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2014-2015, 2018-2019, 2021-2024 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: make_hlds.m.
|
|
%
|
|
% This module defines predicates that construct HLDS goals.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module hlds.make_goal.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_type.
|
|
:- import_module parse_tree.var_table.
|
|
|
|
:- import_module char.
|
|
:- import_module list.
|
|
|
|
% Return the HLDS equivalent of `true'.
|
|
%
|
|
:- func true_goal = hlds_goal.
|
|
:- func true_goal_expr = hlds_goal_expr.
|
|
|
|
:- func true_goal_with_context(prog_context) = hlds_goal.
|
|
|
|
% Return the HLDS equivalent of `fail'.
|
|
%
|
|
:- func fail_goal = hlds_goal.
|
|
:- func fail_goal_expr = hlds_goal_expr.
|
|
:- func fail_goal_info = hlds_goal_info.
|
|
|
|
:- func fail_goal_with_context(prog_context) = hlds_goal.
|
|
|
|
% Create the hlds_goal for a unification, filling in all the as yet
|
|
% unknown slots with dummy values. The unification is constructed as a
|
|
% complicated unification; turning it into some other kind of unification,
|
|
% if appropriate is left to mode analysis. Therefore this predicate
|
|
% shouldn't be used unless you know mode analysis will be run on its
|
|
% output.
|
|
%
|
|
:- pred create_atomic_complicated_unification(prog_var::in, unify_rhs::in,
|
|
prog_context::in, unify_main_context::in, list(unify_sub_context)::in,
|
|
purity::in, hlds_goal::out) is det.
|
|
|
|
% As above, but with default purity pure.
|
|
%
|
|
:- pred create_pure_atomic_complicated_unification(prog_var::in, unify_rhs::in,
|
|
prog_context::in, unify_main_context::in, list(unify_sub_context)::in,
|
|
hlds_goal::out) is det.
|
|
|
|
:- pred make_complicated_unify_assigns(list(prog_var)::in, list(prog_var)::in,
|
|
list(hlds_goal)::out) is det.
|
|
|
|
:- pred make_complicated_unify_assign(prog_var::in, prog_var::in,
|
|
hlds_goal::out) is det.
|
|
|
|
% Create the hlds_goal for a unification that assigns the second variable
|
|
% to the first. The initial inst of the second variable should be
|
|
% ground_inst. The resulting goal has all its fields filled in.
|
|
%
|
|
:- pred make_simple_assign(prog_var::in, prog_var::in,
|
|
unify_main_context::in, list(unify_sub_context)::in,
|
|
hlds_goal::out) is det.
|
|
|
|
% Create the hlds_goal for a unification that tests the equality of two
|
|
% values of atomic types. The resulting goal has all its fields filled in.
|
|
%
|
|
:- pred make_simple_test(prog_var::in, prog_var::in,
|
|
unify_main_context::in, list(unify_sub_context)::in,
|
|
hlds_goal::out) is det.
|
|
|
|
% Produce a goal to construct a given constant. These predicates all
|
|
% fill in the non-locals, instmap_delta and determinism fields of the
|
|
% goal_info of the returned goal. With alias tracking, the instmap_delta
|
|
% will be correct only if the variable being assigned to has no aliases.
|
|
%
|
|
% The cons_id passed to make_const_construction must be fully module
|
|
% qualified.
|
|
%
|
|
:- pred make_int_const_construction(prog_context::in,
|
|
prog_var::in, int::in, hlds_goal::out) is det.
|
|
:- pred make_string_const_construction(prog_context::in,
|
|
prog_var::in, string::in, hlds_goal::out) is det.
|
|
:- pred make_float_const_construction(prog_context::in,
|
|
prog_var::in, float::in, hlds_goal::out) is det.
|
|
:- pred make_char_const_construction(prog_context::in,
|
|
prog_var::in, char::in, hlds_goal::out) is det.
|
|
:- pred make_const_construction(prog_context::in,
|
|
prog_var::in, cons_id::in, hlds_goal::out) is det.
|
|
|
|
:- pred make_int_const_construction_alloc_in_proc(int::in,
|
|
string::in, hlds_goal::out, prog_var::out,
|
|
proc_info::in, proc_info::out) is det.
|
|
:- pred make_string_const_construction_alloc_in_proc(string::in,
|
|
string::in, hlds_goal::out, prog_var::out,
|
|
proc_info::in, proc_info::out) is det.
|
|
:- pred make_float_const_construction_alloc_in_proc(float::in,
|
|
string::in, hlds_goal::out, prog_var::out,
|
|
proc_info::in, proc_info::out) is det.
|
|
:- pred make_char_const_construction_alloc_in_proc(char::in,
|
|
string::in, hlds_goal::out, prog_var::out,
|
|
proc_info::in, proc_info::out) is det.
|
|
:- pred make_const_construction_alloc_in_proc(cons_id::in, mer_type::in,
|
|
is_dummy_type::in, string::in, hlds_goal::out, prog_var::out,
|
|
proc_info::in, proc_info::out) is det.
|
|
|
|
:- pred make_int_const_construction_alloc(int::in, string::in,
|
|
hlds_goal::out, prog_var::out, var_table::in, var_table::out) is det.
|
|
:- pred make_string_const_construction_alloc(string::in, string::in,
|
|
hlds_goal::out, prog_var::out, var_table::in, var_table::out) is det.
|
|
:- pred make_float_const_construction_alloc(float::in, string::in,
|
|
hlds_goal::out, prog_var::out, var_table::in, var_table::out) is det.
|
|
:- pred make_char_const_construction_alloc(char::in, string::in,
|
|
hlds_goal::out, prog_var::out, var_table::in, var_table::out) is det.
|
|
:- pred make_const_construction_alloc(cons_id::in, mer_type::in,
|
|
is_dummy_type::in, string::in, hlds_goal::out, prog_var::out,
|
|
var_table::in, var_table::out) is det.
|
|
|
|
% Produce a goal to construct or deconstruct a unification with a functor.
|
|
% It fills in the non-locals, instmap_delta and determinism fields
|
|
% of the goal_info.
|
|
%
|
|
:- pred construct_functor(prog_var::in, cons_id::in, list(prog_var)::in,
|
|
hlds_goal::out) is det.
|
|
:- pred deconstruct_functor(prog_var::in, cons_id::in, list(prog_var)::in,
|
|
hlds_goal::out) is det.
|
|
|
|
% Produce a goal to construct or deconstruct a tuple containing
|
|
% the given list of arguments, filling in the non-locals,
|
|
% instmap_delta and determinism fields of the goal_info.
|
|
%
|
|
:- pred construct_tuple(prog_var::in, list(prog_var)::in, hlds_goal::out)
|
|
is det.
|
|
:- pred deconstruct_tuple(prog_var::in, list(prog_var)::in, hlds_goal::out)
|
|
is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.hlds_proc_util.
|
|
:- import_module hlds.instmap.
|
|
:- import_module parse_tree.builtin_lib_types.
|
|
:- import_module parse_tree.prog_mode.
|
|
:- import_module parse_tree.set_of_var.
|
|
|
|
:- import_module require.
|
|
:- import_module term_context.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
true_goal = hlds_goal(true_goal_expr, GoalInfo) :-
|
|
instmap_delta_init_reachable(InstMapDelta),
|
|
goal_info_init(set_of_var.init, InstMapDelta, detism_det, purity_pure,
|
|
GoalInfo).
|
|
|
|
true_goal_expr = conj(plain_conj, []).
|
|
|
|
true_goal_with_context(Context) = hlds_goal(GoalExpr, GoalInfo) :-
|
|
hlds_goal(GoalExpr, GoalInfo0) = true_goal,
|
|
goal_info_set_context(Context, GoalInfo0, GoalInfo).
|
|
|
|
fail_goal = hlds_goal(fail_goal_expr, GoalInfo) :-
|
|
instmap_delta_init_unreachable(InstMapDelta),
|
|
goal_info_init(set_of_var.init, InstMapDelta, detism_failure, purity_pure,
|
|
GoalInfo).
|
|
|
|
fail_goal_expr = disj([]).
|
|
|
|
fail_goal_info = GoalInfo :-
|
|
instmap_delta_init_unreachable(InstMapDelta),
|
|
goal_info_init(set_of_var.init, InstMapDelta, detism_failure, purity_pure,
|
|
GoalInfo).
|
|
|
|
fail_goal_with_context(Context) = hlds_goal(GoalExpr, GoalInfo) :-
|
|
hlds_goal(GoalExpr, GoalInfo0) = fail_goal,
|
|
goal_info_set_context(Context, GoalInfo0, GoalInfo).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
create_atomic_complicated_unification(LHS, RHS, Context,
|
|
UnifyMainContext, UnifySubContext, Purity, Goal) :-
|
|
UnifyMode = unify_modes_li_lf_ri_rf(free, free, free, free),
|
|
Unification = complicated_unify(UnifyMode, can_fail, []),
|
|
UnifyContext = unify_context(UnifyMainContext, UnifySubContext),
|
|
goal_info_init_context_purity(Context, Purity, GoalInfo),
|
|
GoalExpr = unify(LHS, RHS, UnifyMode, Unification, UnifyContext),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
create_pure_atomic_complicated_unification(LHS, RHS, Context,
|
|
UnifyMainContext, UnifySubContext, Goal) :-
|
|
create_atomic_complicated_unification(LHS, RHS, Context,
|
|
UnifyMainContext, UnifySubContext, purity_pure, Goal).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_complicated_unify_assigns([], [_ | _], _) :-
|
|
unexpected($pred, "length mismatch").
|
|
make_complicated_unify_assigns([_ | _], [], _) :-
|
|
unexpected($pred, "length mismatch").
|
|
make_complicated_unify_assigns([], [], []).
|
|
make_complicated_unify_assigns([Var1 | Vars1], [Var2 | Vars2],
|
|
[Goal | Goals]) :-
|
|
make_complicated_unify_assign(Var1, Var2, Goal),
|
|
make_complicated_unify_assigns(Vars1, Vars2, Goals).
|
|
|
|
make_complicated_unify_assign(Var1, Var2, Goal) :-
|
|
( if Var1 = Var2 then
|
|
Goal = true_goal
|
|
else
|
|
create_pure_atomic_complicated_unification(Var1, rhs_var(Var2),
|
|
dummy_context, umc_explicit, [], Goal)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_simple_assign(X, Y, UnifyMainContext, UnifySubContext, Goal) :-
|
|
Ground = ground(shared, none_or_default_func),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(free, Ground, Ground, Ground),
|
|
Unification = assign(X, Y),
|
|
UnifyContext = unify_context(UnifyMainContext, UnifySubContext),
|
|
goal_info_init(set_of_var.list_to_set([X, Y]), instmap_delta_bind_var(X),
|
|
detism_det, purity_pure, GoalInfo),
|
|
GoalExpr = unify(X, rhs_var(Y), UnifyMode, Unification, UnifyContext),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
make_simple_test(X, Y, UnifyMainContext, UnifySubContext, Goal) :-
|
|
Ground = ground(shared, none_or_default_func),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(Ground, Ground, Ground, Ground),
|
|
Unification = simple_test(X, Y),
|
|
UnifyContext = unify_context(UnifyMainContext, UnifySubContext),
|
|
goal_info_init(set_of_var.list_to_set([X, Y]), instmap_delta_bind_no_var,
|
|
detism_semi, purity_pure, GoalInfo),
|
|
GoalExpr = unify(X, rhs_var(Y), UnifyMode, Unification, UnifyContext),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_int_const_construction(Context, Var, Int, Goal) :-
|
|
ConsId = some_int_const(int_const(Int)),
|
|
make_const_construction(Context, Var, ConsId, Goal).
|
|
|
|
make_string_const_construction(Context, Var, String, Goal) :-
|
|
make_const_construction(Context, Var, string_const(String), Goal).
|
|
|
|
make_float_const_construction(Context, Var, Float, Goal) :-
|
|
make_const_construction(Context, Var, float_const(Float), Goal).
|
|
|
|
make_char_const_construction(Context, Var, Char, Goal) :-
|
|
make_const_construction(Context, Var, char_const(Char), Goal).
|
|
|
|
make_const_construction(Context, Var, ConsId, Goal) :-
|
|
RHS = rhs_functor(ConsId, is_not_exist_constr, []),
|
|
Inst = bound(unique, inst_test_results_fgtc, [bound_functor(ConsId, [])]),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(free, Inst, Inst, Inst),
|
|
Unification = construct(Var, ConsId, [], [],
|
|
construct_dynamically, cell_is_unique, no_construct_sub_info),
|
|
UnifyContext = unify_context(umc_explicit, []),
|
|
GoalExpr = unify(Var, RHS, UnifyMode, Unification, UnifyContext),
|
|
NonLocals = set_of_var.make_singleton(Var),
|
|
instmap_delta_init_reachable(InstMapDelta0),
|
|
instmap_delta_insert_var(Var, Inst, InstMapDelta0, InstMapDelta),
|
|
goal_info_init(NonLocals, InstMapDelta, detism_det, purity_pure, Context,
|
|
GoalInfo),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_int_const_construction_alloc_in_proc(Int, Name, Goal, Var,
|
|
!ProcInfo) :-
|
|
proc_info_create_var_from_type(Name, int_type, is_not_dummy_type,
|
|
Var, !ProcInfo),
|
|
make_int_const_construction(dummy_context, Var, Int, Goal).
|
|
|
|
make_string_const_construction_alloc_in_proc(String, Name, Goal, Var,
|
|
!ProcInfo) :-
|
|
proc_info_create_var_from_type(Name, string_type, is_not_dummy_type,
|
|
Var, !ProcInfo),
|
|
make_string_const_construction(dummy_context, Var, String, Goal).
|
|
|
|
make_float_const_construction_alloc_in_proc(Float, Name, Goal, Var,
|
|
!ProcInfo) :-
|
|
proc_info_create_var_from_type(Name, float_type, is_not_dummy_type,
|
|
Var, !ProcInfo),
|
|
make_float_const_construction(dummy_context, Var, Float, Goal).
|
|
|
|
make_char_const_construction_alloc_in_proc(Char, Name, Goal, Var,
|
|
!ProcInfo) :-
|
|
proc_info_create_var_from_type(Name, char_type, is_not_dummy_type, Var,
|
|
!ProcInfo),
|
|
make_char_const_construction(dummy_context, Var, Char, Goal).
|
|
|
|
make_const_construction_alloc_in_proc(ConsId, Type, IsDummy, Name, Goal, Var,
|
|
!ProcInfo) :-
|
|
proc_info_create_var_from_type(Name, Type, IsDummy, Var, !ProcInfo),
|
|
make_const_construction(dummy_context, Var, ConsId, Goal).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_int_const_construction_alloc(Int, Name, Goal, Var,
|
|
!VarTable) :-
|
|
Entry = vte(Name, int_type, is_not_dummy_type),
|
|
add_var_entry(Entry, Var, !VarTable),
|
|
make_int_const_construction(dummy_context, Var, Int, Goal).
|
|
|
|
make_string_const_construction_alloc(String, Name, Goal, Var,
|
|
!VarTable) :-
|
|
Entry = vte(Name, string_type, is_not_dummy_type),
|
|
add_var_entry(Entry, Var, !VarTable),
|
|
make_string_const_construction(dummy_context, Var, String, Goal).
|
|
|
|
make_float_const_construction_alloc(Float, Name, Goal, Var,
|
|
!VarTable) :-
|
|
Entry = vte(Name, float_type, is_not_dummy_type),
|
|
add_var_entry(Entry, Var, !VarTable),
|
|
make_float_const_construction(dummy_context, Var, Float, Goal).
|
|
|
|
make_char_const_construction_alloc(Char, Name, Goal, Var,
|
|
!VarTable) :-
|
|
Entry = vte(Name, char_type, is_not_dummy_type),
|
|
add_var_entry(Entry, Var, !VarTable),
|
|
make_char_const_construction(dummy_context, Var, Char, Goal).
|
|
|
|
make_const_construction_alloc(ConsId, Type, IsDummyType, Name, Goal, Var,
|
|
!VarTable) :-
|
|
Entry = vte(Name, Type, IsDummyType),
|
|
add_var_entry(Entry, Var, !VarTable),
|
|
make_const_construction(dummy_context, Var, ConsId, Goal).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
construct_functor(Var, ConsId, Args, Goal) :-
|
|
list.length(Args, Arity),
|
|
RHS = rhs_functor(ConsId, is_not_exist_constr, Args),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(free_inst, ground_inst,
|
|
ground_inst, ground_inst),
|
|
list.duplicate(Arity, UnifyMode, ArgModes),
|
|
Unification = construct(Var, ConsId, Args, ArgModes,
|
|
construct_dynamically, cell_is_unique, no_construct_sub_info),
|
|
UnifyContext = unify_context(umc_explicit, []),
|
|
Unify = unify(Var, RHS, UnifyMode, Unification, UnifyContext),
|
|
set_of_var.list_to_set([Var | Args], NonLocals),
|
|
InstMapDelta = instmap_delta_bind_var(Var),
|
|
goal_info_init(NonLocals, InstMapDelta, detism_det, purity_pure, GoalInfo),
|
|
Goal = hlds_goal(Unify, GoalInfo).
|
|
|
|
deconstruct_functor(Var, ConsId, Args, Goal) :-
|
|
list.length(Args, Arity),
|
|
RHS = rhs_functor(ConsId, is_not_exist_constr, Args),
|
|
UnifyMode = unify_modes_li_lf_ri_rf(ground_inst, ground_inst,
|
|
free_inst, ground_inst),
|
|
list.duplicate(Arity, UnifyMode, ArgModes),
|
|
UnifyContext = unify_context(umc_explicit, []),
|
|
Unification = deconstruct(Var, ConsId, Args, ArgModes, cannot_fail,
|
|
cannot_cgc),
|
|
Unify = unify(Var, RHS, UnifyMode, Unification, UnifyContext),
|
|
set_of_var.list_to_set([Var | Args], NonLocals),
|
|
InstMapDelta = instmap_delta_bind_vars(Args),
|
|
goal_info_init(NonLocals, InstMapDelta, detism_det, purity_pure, GoalInfo),
|
|
Goal = hlds_goal(Unify, GoalInfo).
|
|
|
|
construct_tuple(Tuple, Args, Goal) :-
|
|
list.length(Args, Arity),
|
|
ConsId = tuple_cons(Arity),
|
|
construct_functor(Tuple, ConsId, Args, Goal).
|
|
|
|
deconstruct_tuple(Tuple, Args, Goal) :-
|
|
list.length(Args, Arity),
|
|
ConsId = tuple_cons(Arity),
|
|
deconstruct_functor(Tuple, ConsId, Args, Goal).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module hlds.make_goal.
|
|
%---------------------------------------------------------------------------%
|