mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 06:14:59 +00:00
Estimated hours taken: 20 Branches: main Change the types that represent forward and reverse goal paths from being wrappers around lists of steps, to being full discriminated union types. This is meant to accomplish two objectives. First, since taking the wrappers off and putting them back on is inconvenient, code often dealt with naked lists of steps, with the meaning of those steps sometimes being unclear. Second, in a future change I intend to change the way the debugger represents goal paths from being strings to being statically allocated terms of the reverse_goal_path type. This should have two benefits. One is reduced memory consumption, since two different goal path strings cannot share memory but two different reverse goal paths can share the memory containing their common tail (the goal paths steps near the root). The other is that the declarative debugger won't need to do any conversion from string to structure, and should therefore be faster. Having the compiler generate static terms of the reverse_goal_path type into the .c files it generates for every Mercury program being compiled with debugging requires it to have access to the definition of that type and all its components. The best way to do this is to put all those types into a new builtin module in the library (a debugging equivalent of e.g. profiling_builtin.m). We cannot put the definition of the list type into that module without causing considerable backward incompatibilities. mdbcomp/mdbcomp.goal_path.m: Make the change described above. Add some more predicates implementing abstract operations on goal paths. browser/declarative_tree.m: compiler/goal_path.m: compiler/goal_util.m: compiler/hlds_goal.m: compiler/introduce_parallelism.m: compiler/mode_ordering.m: compiler/push_goals_together.m: compiler/rbmm.condition_renaming.m: compiler/trace_gen.m: compiler/tupling.m: compiler/unneeded_code.m: deep_profiler/autopar_costs.m: deep_profiler/autopar_reports.m: deep_profiler/autopar_search_callgraph.m: deep_profiler/autopar_search_goals.m: deep_profiler/create_report.m: deep_profiler/message.m: deep_profiler/program_representation_utils.m: deep_profiler/read_profile.m: deep_profiler/recursion_patterns.m: deep_profiler/var_use_analysis.m: Conform to the change in representation. In some cases, remove predicates whose only job was to manipulate wrappers. In others, replace concrete operations on lists of steps with abstract operations on goal paths. compiler/mode_constraints.m: Comment out some code that I do not understand, which I think never worked (not surprising, since the whole module has never been operational). mdbcomp/slice_and_dice.m: Since this diff changes the types representing goal paths, it also changes their default ordering, as implemented by builtin.compare. When ordering slices and dices by goal paths, make the ordering explicitly work on the forward goal path, since ordering by the reverse goal path (the actual data being used) gives nonintuitive results. library/list.m: Speed up some code. mdbcomp/feedback.automatic_parallelism.m: Fix some formatting.
463 lines
20 KiB
Mathematica
463 lines
20 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1997-2011 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: goal_path.m.
|
|
% Main author: zs.
|
|
%
|
|
% This module looks after goal ids, which give every goal a unique id within
|
|
% its procedure definition, and goal paths, which map each goal id to its
|
|
% goal's position in the procedure definition.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module hlds.goal_path.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_clauses.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module mdbcomp.goal_path.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% IMPORTANT: the type constraint_id in hlds_data.m makes use of goal ids
|
|
% to identify goals that impose constraints between the typechecking pass
|
|
% and the polymorphism pass. For this reason, goal ids should not be
|
|
% recalculated anywhere between these two passes. See the XXX comment
|
|
% near the declaration of constraint_id.
|
|
%
|
|
:- pred fill_goal_id_slots_in_proc(module_info::in,
|
|
containing_goal_map::out, proc_info::in, proc_info::out) is det.
|
|
|
|
:- pred fill_goal_id_slots_in_proc_body(module_info::in, vartypes::in,
|
|
containing_goal_map::out, hlds_goal::in, hlds_goal::out) is det.
|
|
|
|
% Fill in the goal_ids for goals in the clauses_info.
|
|
% Clauses are given goal paths `disj(1)', ..., `disj(N)'.
|
|
%
|
|
:- pred fill_goal_id_slots_in_clauses(module_info::in,
|
|
containing_goal_map::out, clauses_info::in, clauses_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Fill in the goal path slots in the given procedure.
|
|
% This predicate is here ONLY to support the RBMM and GTGC modules,
|
|
% which are hard to transition to make use of goal_ids instead;
|
|
% all new code should instead use the predicates above that fill in
|
|
% the goal_id slots instead.
|
|
%
|
|
:- pred fill_goal_path_slots_in_proc(module_info::in,
|
|
proc_info::in, proc_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.type_util.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module mdbcomp.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type slot_info
|
|
---> slot_info(
|
|
slot_info_module_info :: module_info,
|
|
slot_info_vartypes :: vartypes
|
|
).
|
|
|
|
fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap, !ProcInfo) :-
|
|
proc_info_get_vartypes(!.ProcInfo, VarTypes),
|
|
proc_info_get_goal(!.ProcInfo, Goal0),
|
|
fill_goal_id_slots_in_proc_body(ModuleInfo, VarTypes,
|
|
ContainingGoalMap, Goal0, Goal),
|
|
proc_info_set_goal(Goal, !ProcInfo).
|
|
|
|
fill_goal_id_slots_in_proc_body(ModuleInfo, VarTypes, ContainingGoalMap,
|
|
Goal0, Goal) :-
|
|
SlotInfo = slot_info(ModuleInfo, VarTypes),
|
|
fill_goal_id_slots(SlotInfo, whole_body_goal, 0, _,
|
|
map.init, ContainingGoalMap, Goal0, Goal).
|
|
|
|
fill_goal_id_slots_in_clauses(ModuleInfo, ContainingGoalMap,
|
|
ClausesInfo0, ClausesInfo) :-
|
|
clauses_info_get_clauses_rep(ClausesInfo0, ClausesRep0, ItemNumbers),
|
|
get_clause_list(ClausesRep0, Clauses0),
|
|
clauses_info_get_vartypes(ClausesInfo0, VarTypes),
|
|
SlotInfo = slot_info(ModuleInfo, VarTypes),
|
|
list.map_foldl3(fill_slots_in_clause(SlotInfo),
|
|
Clauses0, Clauses, 1, _, 1, _, map.init, ContainingGoalMap),
|
|
set_clause_list(Clauses, ClausesRep),
|
|
clauses_info_set_clauses_rep(ClausesRep, ItemNumbers,
|
|
ClausesInfo0, ClausesInfo).
|
|
|
|
:- pred fill_slots_in_clause(slot_info::in, clause::in, clause::out,
|
|
int::in, int::out, int::in, int::out,
|
|
containing_goal_map::in, containing_goal_map::out) is det.
|
|
|
|
fill_slots_in_clause(SlotInfo, Clause0, Clause, !GoalNum, !ClauseNum,
|
|
!ContainingGoalMap) :-
|
|
Goal0 = Clause0 ^ clause_body,
|
|
ContainingGoal = containing_goal(whole_body_goal_id,
|
|
step_disj(!.ClauseNum)),
|
|
!:ClauseNum = !.ClauseNum + 1,
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal),
|
|
Clause = Clause0 ^ clause_body := Goal.
|
|
|
|
fill_goal_path_slots_in_proc(ModuleInfo, !Proc) :-
|
|
proc_info_get_goal(!.Proc, Goal0),
|
|
proc_info_get_vartypes(!.Proc, VarTypes),
|
|
SlotInfo = slot_info(ModuleInfo, VarTypes),
|
|
fill_goal_path_slots(rgp_nil, SlotInfo, Goal0, Goal),
|
|
proc_info_set_goal(Goal, !Proc).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred fill_goal_id_slots(slot_info::in, containing_goal::in,
|
|
int::in, int::out, containing_goal_map::in, containing_goal_map::out,
|
|
hlds_goal::in, hlds_goal::out) is det.
|
|
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
GoalId = goal_id(!.GoalNum),
|
|
!:GoalNum = !.GoalNum + 1,
|
|
goal_info_set_goal_id(GoalId, GoalInfo0, GoalInfo),
|
|
map.det_insert(GoalId, ContainingGoal, !ContainingGoalMap),
|
|
(
|
|
( GoalExpr0 = plain_call(_, _, _, _, _, _)
|
|
; GoalExpr0 = generic_call(_, _, _, _)
|
|
; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
|
|
),
|
|
GoalExpr = GoalExpr0
|
|
;
|
|
GoalExpr0 = unify(LHS, RHS0, Mode, Kind, Context),
|
|
(
|
|
RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
|
|
NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal0),
|
|
fill_goal_id_slots(SlotInfo,
|
|
containing_goal(GoalId, step_lambda),
|
|
!GoalNum, !ContainingGoalMap, LambdaGoal0, LambdaGoal),
|
|
RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
|
|
NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal),
|
|
GoalExpr = unify(LHS, RHS, Mode, Kind, Context)
|
|
;
|
|
( RHS0 = rhs_var(_)
|
|
; RHS0 = rhs_functor(_, _, _)
|
|
),
|
|
GoalExpr = GoalExpr0
|
|
)
|
|
;
|
|
GoalExpr0 = conj(ConjType, Goals0),
|
|
fill_conj_id_slots(SlotInfo, GoalId, 0, !GoalNum, !ContainingGoalMap,
|
|
Goals0, Goals),
|
|
GoalExpr = conj(ConjType, Goals)
|
|
;
|
|
GoalExpr0 = disj(Goals0),
|
|
fill_disj_id_slots(SlotInfo, GoalId, 0, !GoalNum, !ContainingGoalMap,
|
|
Goals0, Goals),
|
|
GoalExpr = disj(Goals)
|
|
;
|
|
GoalExpr0 = switch(Var, CanFail, Cases0),
|
|
VarTypes = SlotInfo ^ slot_info_vartypes,
|
|
ModuleInfo = SlotInfo ^ slot_info_module_info,
|
|
map.lookup(VarTypes, Var, Type),
|
|
( switch_type_num_functors(ModuleInfo, Type, NumFunctors) ->
|
|
MaybeNumFunctors = known_num_functors_in_type(NumFunctors)
|
|
;
|
|
MaybeNumFunctors = unknown_num_functors_in_type
|
|
),
|
|
fill_switch_id_slots(SlotInfo, GoalId, 0, MaybeNumFunctors, !GoalNum,
|
|
!ContainingGoalMap, Cases0, Cases),
|
|
GoalExpr = switch(Var, CanFail, Cases)
|
|
;
|
|
GoalExpr0 = negation(SubGoal0),
|
|
fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_neg),
|
|
!GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
|
|
GoalExpr = negation(SubGoal)
|
|
;
|
|
GoalExpr0 = scope(Reason, SubGoal0),
|
|
% We should consider not filling in the goal path slots inside
|
|
% from_ground_term_construct scopes, since we do not use them
|
|
% for anything.
|
|
SubGoal0 = hlds_goal(_, InnerInfo),
|
|
OuterDetism = goal_info_get_determinism(GoalInfo),
|
|
InnerDetism = goal_info_get_determinism(InnerInfo),
|
|
( InnerDetism = OuterDetism ->
|
|
MaybeCut = scope_is_no_cut
|
|
;
|
|
MaybeCut = scope_is_cut
|
|
),
|
|
fill_goal_id_slots(SlotInfo,
|
|
containing_goal(GoalId, step_scope(MaybeCut)),
|
|
!GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
|
|
GoalExpr = scope(Reason, SubGoal)
|
|
;
|
|
GoalExpr0 = if_then_else(A, Cond0, Then0, Else0),
|
|
fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_cond),
|
|
!GoalNum, !ContainingGoalMap, Cond0, Cond),
|
|
fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_then),
|
|
!GoalNum, !ContainingGoalMap, Then0, Then),
|
|
fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_else),
|
|
!GoalNum, !ContainingGoalMap, Else0, Else),
|
|
GoalExpr = if_then_else(A, Cond, Then, Else)
|
|
;
|
|
GoalExpr0 = shorthand(ShortHand0),
|
|
(
|
|
ShortHand0 = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
|
|
MainGoal0, OrElseGoals0, OrElseInners),
|
|
fill_goal_id_slots(SlotInfo,
|
|
containing_goal(GoalId, step_atomic_main),
|
|
!GoalNum, !ContainingGoalMap, MainGoal0, MainGoal),
|
|
fill_orelse_id_slots(SlotInfo, GoalId, 0, !GoalNum,
|
|
!ContainingGoalMap, OrElseGoals0, OrElseGoals),
|
|
ShortHand = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
|
|
MainGoal, OrElseGoals, OrElseInners)
|
|
;
|
|
ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
|
|
fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_try),
|
|
!GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
|
|
ShortHand = try_goal(MaybeIO, ResultVar, SubGoal)
|
|
;
|
|
ShortHand0 = bi_implication(_, _),
|
|
% These should have been expanded out by now.
|
|
unexpected($module, $pred, "bi_implication")
|
|
),
|
|
GoalExpr = shorthand(ShortHand)
|
|
),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
:- pred fill_conj_id_slots(slot_info::in, goal_id::in, int::in,
|
|
int::in, int::out, containing_goal_map::in, containing_goal_map::out,
|
|
list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_conj_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
|
|
fill_conj_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
ContainingGoal = containing_goal(GoalId, step_conj(N1)),
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal),
|
|
fill_conj_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
|
|
Goals0, Goals).
|
|
|
|
:- pred fill_disj_id_slots(slot_info::in, goal_id::in, int::in,
|
|
int::in, int::out, containing_goal_map::in, containing_goal_map::out,
|
|
list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_disj_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
|
|
fill_disj_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
ContainingGoal = containing_goal(GoalId, step_disj(N1)),
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal),
|
|
fill_disj_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
|
|
Goals0, Goals).
|
|
|
|
:- pred fill_switch_id_slots(slot_info::in, goal_id::in,
|
|
int::in, maybe_switch_num_functors::in, int::in, int::out,
|
|
containing_goal_map::in, containing_goal_map::out,
|
|
list(case)::in, list(case)::out) is det.
|
|
|
|
fill_switch_id_slots(_, _, _, _, !GoalNum, !ContainingGoalMap, [], []).
|
|
fill_switch_id_slots(SlotInfo, GoalId, N0, MaybeNumFunctors,
|
|
!GoalNum, !ContainingGoalMap, [Case0 | Cases0], [Case | Cases]) :-
|
|
Case0 = case(MainConsId, OtherConsIds, Goal0),
|
|
N1 = N0 + 1,
|
|
ContainingGoal =
|
|
containing_goal(GoalId, step_switch(N1, MaybeNumFunctors)),
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal),
|
|
Case = case(MainConsId, OtherConsIds, Goal),
|
|
fill_switch_id_slots(SlotInfo, GoalId, N1, MaybeNumFunctors,
|
|
!GoalNum, !ContainingGoalMap, Cases0, Cases).
|
|
|
|
:- pred fill_orelse_id_slots(slot_info::in, goal_id::in, int::in,
|
|
int::in, int::out, containing_goal_map::in, containing_goal_map::out,
|
|
list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_orelse_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
|
|
fill_orelse_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
ContainingGoal = containing_goal(GoalId, step_atomic_orelse(N1)),
|
|
fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
|
|
Goal0, Goal),
|
|
fill_orelse_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
|
|
Goals0, Goals).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred fill_goal_path_slots(reverse_goal_path::in, slot_info::in,
|
|
hlds_goal::in, hlds_goal::out) is det.
|
|
|
|
fill_goal_path_slots(RevPath0, SlotInfo, Goal0, Goal) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
goal_info_set_reverse_goal_path(RevPath0, GoalInfo0, GoalInfo),
|
|
(
|
|
GoalExpr0 = conj(ConjType, Goals0),
|
|
fill_conj_path_slots(RevPath0, 0, SlotInfo, Goals0, Goals),
|
|
GoalExpr = conj(ConjType, Goals)
|
|
;
|
|
GoalExpr0 = disj(Goals0),
|
|
fill_disj_path_slots(RevPath0, 0, SlotInfo, Goals0, Goals),
|
|
GoalExpr = disj(Goals)
|
|
;
|
|
GoalExpr0 = switch(Var, CanFail, Cases0),
|
|
VarTypes = SlotInfo ^ slot_info_vartypes,
|
|
ModuleInfo = SlotInfo ^ slot_info_module_info,
|
|
map.lookup(VarTypes, Var, Type),
|
|
( switch_type_num_functors(ModuleInfo, Type, NumFunctors) ->
|
|
MaybeNumFunctors = known_num_functors_in_type(NumFunctors)
|
|
;
|
|
MaybeNumFunctors = unknown_num_functors_in_type
|
|
),
|
|
fill_switch_path_slots(RevPath0, 0, MaybeNumFunctors, SlotInfo,
|
|
Cases0, Cases),
|
|
GoalExpr = switch(Var, CanFail, Cases)
|
|
;
|
|
GoalExpr0 = negation(SubGoal0),
|
|
RevPath = rgp_cons(RevPath0, step_neg),
|
|
fill_goal_path_slots(RevPath, SlotInfo, SubGoal0, SubGoal),
|
|
GoalExpr = negation(SubGoal)
|
|
;
|
|
GoalExpr0 = scope(Reason, SubGoal0),
|
|
% We should consider not filling in the goal path slots inside
|
|
% from_ground_term_construct scopes, since we do not use them
|
|
% for anything.
|
|
SubGoal0 = hlds_goal(_, InnerInfo),
|
|
OuterDetism = goal_info_get_determinism(GoalInfo),
|
|
InnerDetism = goal_info_get_determinism(InnerInfo),
|
|
( InnerDetism = OuterDetism ->
|
|
MaybeCut = scope_is_no_cut
|
|
;
|
|
MaybeCut = scope_is_cut
|
|
),
|
|
RevPath = rgp_cons(RevPath0, step_scope(MaybeCut)),
|
|
fill_goal_path_slots(RevPath, SlotInfo, SubGoal0, SubGoal),
|
|
GoalExpr = scope(Reason, SubGoal)
|
|
;
|
|
GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
|
|
RevPathCond = rgp_cons(RevPath0, step_ite_cond),
|
|
RevPathThen = rgp_cons(RevPath0, step_ite_then),
|
|
RevPathElse = rgp_cons(RevPath0, step_ite_else),
|
|
fill_goal_path_slots(RevPathCond, SlotInfo, Cond0, Cond),
|
|
fill_goal_path_slots(RevPathThen, SlotInfo, Then0, Then),
|
|
fill_goal_path_slots(RevPathElse, SlotInfo, Else0, Else),
|
|
GoalExpr = if_then_else(Vars, Cond, Then, Else)
|
|
;
|
|
GoalExpr0 = unify(LHS, RHS0, Mode, Kind, Context),
|
|
(
|
|
RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
|
|
NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal0),
|
|
fill_goal_path_slots(RevPath0, SlotInfo, LambdaGoal0, LambdaGoal),
|
|
RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
|
|
NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal)
|
|
;
|
|
( RHS0 = rhs_var(_)
|
|
; RHS0 = rhs_functor(_, _, _)
|
|
),
|
|
RHS = RHS0
|
|
),
|
|
GoalExpr = unify(LHS, RHS, Mode, Kind, Context)
|
|
;
|
|
( GoalExpr0 = plain_call(_, _, _, _, _, _)
|
|
; GoalExpr0 = generic_call(_, _, _, _)
|
|
; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
|
|
),
|
|
GoalExpr = GoalExpr0
|
|
;
|
|
GoalExpr0 = shorthand(ShortHand0),
|
|
(
|
|
ShortHand0 = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
|
|
MainGoal0, OrElseGoals0, OrElseInners),
|
|
RevPathMain = rgp_cons(RevPath0, step_atomic_main),
|
|
fill_goal_path_slots(RevPathMain, SlotInfo, MainGoal0, MainGoal),
|
|
fill_orelse_path_slots(RevPath0, 0, SlotInfo,
|
|
OrElseGoals0, OrElseGoals),
|
|
ShortHand = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
|
|
MainGoal, OrElseGoals, OrElseInners)
|
|
;
|
|
ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
|
|
RevPath = rgp_cons(RevPath0, step_try),
|
|
fill_goal_path_slots(RevPath, SlotInfo, SubGoal0, SubGoal),
|
|
ShortHand = try_goal(MaybeIO, ResultVar, SubGoal)
|
|
;
|
|
ShortHand0 = bi_implication(_, _),
|
|
% These should have been expanded out by now.
|
|
unexpected($module, $pred, "bi_implication")
|
|
),
|
|
GoalExpr = shorthand(ShortHand)
|
|
),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
:- pred fill_conj_path_slots(reverse_goal_path::in, int::in, slot_info::in,
|
|
list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_conj_path_slots(_, _, _, [], []).
|
|
fill_conj_path_slots(RevPath0, N0, SlotInfo,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
fill_goal_path_slots(rgp_cons(RevPath0, step_conj(N1)), SlotInfo,
|
|
Goal0, Goal),
|
|
fill_conj_path_slots(RevPath0, N1, SlotInfo, Goals0, Goals).
|
|
|
|
:- pred fill_disj_path_slots(reverse_goal_path::in, int::in, slot_info::in,
|
|
list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_disj_path_slots(_, _, _, [], []).
|
|
fill_disj_path_slots(RevPath0, N0, SlotInfo,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
fill_goal_path_slots(rgp_cons(RevPath0, step_disj(N1)), SlotInfo,
|
|
Goal0, Goal),
|
|
fill_disj_path_slots(RevPath0, N1, SlotInfo, Goals0, Goals).
|
|
|
|
:- pred fill_switch_path_slots(reverse_goal_path::in,
|
|
int::in, maybe_switch_num_functors::in, slot_info::in,
|
|
list(case)::in, list(case)::out) is det.
|
|
|
|
fill_switch_path_slots(_, _, _, _, [], []).
|
|
fill_switch_path_slots(RevPath0, N0, MaybeNumFunctors, SlotInfo,
|
|
[Case0 | Cases0], [Case | Cases]) :-
|
|
Case0 = case(MainConsId, OtherConsIds, Goal0),
|
|
N1 = N0 + 1,
|
|
fill_goal_path_slots(rgp_cons(RevPath0, step_switch(N1, MaybeNumFunctors)),
|
|
SlotInfo, Goal0, Goal),
|
|
Case = case(MainConsId, OtherConsIds, Goal),
|
|
fill_switch_path_slots(RevPath0, N1, MaybeNumFunctors, SlotInfo,
|
|
Cases0, Cases).
|
|
|
|
:- pred fill_orelse_path_slots(reverse_goal_path::in, int::in,
|
|
slot_info::in, list(hlds_goal)::in, list(hlds_goal)::out) is det.
|
|
|
|
fill_orelse_path_slots(_, _, _, [], []).
|
|
fill_orelse_path_slots(RevPath0, N0, SlotInfo,
|
|
[Goal0 | Goals0], [Goal | Goals]) :-
|
|
N1 = N0 + 1,
|
|
fill_goal_path_slots(rgp_cons(RevPath0, step_atomic_orelse(N1)), SlotInfo,
|
|
Goal0, Goal),
|
|
fill_orelse_path_slots(RevPath0, N1, SlotInfo, Goals0, Goals).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module hlds.goal_path.
|
|
%-----------------------------------------------------------------------------%
|