mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
compiler/prog_type_construct.m:
New module for constructing types.
compiler/prog_type_repn.m:
New module for testing things related to type representation.
compiler/prog_type_scan.m:
New module for gather type vars in types.
compiler/prog_type_test.m:
New module containing simple tests on types.
compiler/prog_type_unify.m:
New module for testing whether two types unify, or whether
one type subsumes another.
compiler/prog_type.m:
Delete the code moved to the new modules.
compiler/parse_tree.m:
Include the new modules.
compiler/notes/compiler_design.html:
Document the new modules.
compiler/*.m:
Conform to the changes above, by adjusting imports as needed,
and by deleting any explicit module qualifications that
this diff makes obsolete.
384 lines
16 KiB
Mathematica
384 lines
16 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2014-2015 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, unify_sub_contexts::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, unify_sub_contexts::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, unify_sub_contexts::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, unify_sub_contexts::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.
|
|
%
|
|
% Ths 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.
|
|
%---------------------------------------------------------------------------%
|