Files
mercury/compiler/make_goal.m
Julien Fischer 153590a30f Update and fix more copyright notices.
compiler/*.m:
    As above.
2024-12-30 16:01:59 +11:00

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