Files
mercury/compiler/constraint.m
Zoltan Somogyi 2833bfffb7 Divided the old hlds.m into four files:
Estimated hours taken: 10

hlds, hlds_module, hlds_pred, hlds_goal, hlds_data:
	Divided the old hlds.m into four files:

	hlds_module.m defines the data structures that deal with issues
	that are wider than a single predicate. These data structures are
	the module_info structure, dependency_info, the predicate table
	and the shape table.

	hlds_pred.m defined pred_info and proc_info, pred_id and proc_id.

	hlds_goal.m defines hlds__goal, hlds__goal_{expr,info}, and the
	other parts of goal structures.

	hlsd_data.m defines the HLDS types that deal with issues related
	to data and its representation: function symbols, types, insts, modes.
	It also defines the types related to determinism.

	hlds.m is now an empty module. I have not removed it from CVS
	because we may need the name hlds.m again, and CVS does not like
	the reuse of a name once removed.

other modules:
	Import the necessary part of hlds.

det_analysis:
	Define a type that was up to now improperly defined in hlds.m.

prog_io:
	Move the definition of type determinism to hlds_data. This decision
	may need to be revisited when prog_io is broken up.

dnf, lambda:
	Simplify the task of defining predicates.

llds:
	Fix some comments.

mercury_compile:
	If the option -d all is given, dump all HLDS stages.

shape, unused_args:
	Fix formatting.
1996-04-02 12:12:24 +00:00

460 lines
16 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1995 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: constraint.m
% Main author: bromage.
%
% This module will eventually perform constraint propagation on
% an entire module. At the moment, though, it just does propagation
% within a single goal. The code is
%-----------------------------------------------------------------------------%
:- module constraint.
:- interface.
:- import_module hlds_module, llds.
:- import_module io.
:- pred constraint_propagation(module_info, module_info, io__state, io__state).
:- mode constraint_propagation(in, out, di, uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds_pred, hlds_goal, hlds_data.
:- import_module mode_util, passes_aux, code_aux, prog_io.
:- import_module delay_info, mode_info, inst_match, modes.
:- import_module transform, options, globals.
:- import_module mercury_to_mercury, hlds_out, dependency_graph.
:- import_module bool, list, map, set, std_util, assoc_list, string.
:- import_module varset, term, require.
:- type constraint == hlds__goal.
%-----------------------------------------------------------------------------%
constraint_propagation(ModuleInfo0, ModuleInfo) -->
{ module_info_ensure_dependency_info(ModuleInfo0, ModuleInfo1) },
{ module_info_dependency_info(ModuleInfo1, DepInfo) },
{ hlds__dependency_info_get_dependency_ordering(DepInfo, DepOrd) },
constraint_propagation2(DepOrd, ModuleInfo1, ModuleInfo).
:- pred constraint_propagation2(dependency_ordering, module_info, module_info,
io__state, io__state).
:- mode constraint_propagation2(in, in, out, di, uo) is det.
constraint_propagation2([], ModuleInfo, ModuleInfo) --> [].
constraint_propagation2([C | Cs], ModuleInfo0, ModuleInfo) -->
constraint_propagation3(C, ModuleInfo0, ModuleInfo1),
constraint_propagation2(Cs, ModuleInfo1, ModuleInfo).
:- pred constraint_propagation3(list(pred_proc_id), module_info, module_info,
io__state, io__state).
:- mode constraint_propagation3(in, in, out, di, uo) is det.
constraint_propagation3([], ModuleInfo, ModuleInfo) --> [].
constraint_propagation3([proc(Pred, Proc) | Rest], ModuleInfo0, ModuleInfo) -->
constraint__transform_proc_1(Pred, Proc, ModuleInfo0, ModuleInfo1),
modecheck_proc(Proc, Pred, ModuleInfo1, ModuleInfo2, Errs),
( { Errs \= 0 } ->
{ error("constraint_propagation3") }
;
[]
),
constraint_propagation3(Rest, ModuleInfo2, ModuleInfo).
%-----------------------------------------------------------------------------%
:- pred constraint__transform_proc_1(pred_id, proc_id, module_info, module_info,
io__state, io__state).
:- mode constraint__transform_proc_1(in, in, in, out, di, uo) is det.
constraint__transform_proc_1(PredId, ProcId, ModuleInfo0, ModuleInfo,
IoState0, IoState) :-
module_info_preds(ModuleInfo0, PredTable0),
map__lookup(PredTable0, PredId, PredInfo0),
pred_info_procedures(PredInfo0, ProcTable0),
map__lookup(ProcTable0, ProcId, ProcInfo0),
pred_info_name(PredInfo0, Name),
proc_info_declared_determinism(ProcInfo0, Det),
proc_info_argmodes(ProcInfo0, Modes),
varset__init(ModeVarSet),
io__write_string("\nProcessing: ", IoState0, IoState1),
mercury_output_pred_mode_subdecl(ModeVarSet, unqualified(Name),
Modes, Det, Context, IoState1, IoState2),
io__write_string("\n", IoState2, IoState3),
IoState3 = IoState99,
proc_info_goal(ProcInfo0, Goal0),
proc_info_variables(ProcInfo0, VarSet0),
varset__vars(VarSet0, VarList),
set__list_to_set(VarList, VarSet1),
proc_info_get_initial_instmap(ProcInfo0, ModuleInfo0, InstMap0),
proc_info_context(ProcInfo0, Context),
mode_info_init(IoState99, ModuleInfo0, PredId, ProcId,
Context, VarSet1, InstMap0, ModeInfo0),
constraint__propagate_goal(Goal0, Goal, ModeInfo0, ModeInfo),
mode_info_get_io_state(ModeInfo, IoState),
mode_info_get_varset(ModeInfo, VarSet),
mode_info_get_var_types(ModeInfo, VarTypes),
mode_info_get_module_info(ModeInfo, ModuleInfo1),
proc_info_set_variables(ProcInfo0, VarSet, ProcInfo1),
proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
proc_info_set_goal(ProcInfo2, Goal, ProcInfo),
map__set(ProcTable0, ProcId, ProcInfo, ProcTable),
pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
map__set(PredTable0, PredId, PredInfo, PredTable),
module_info_set_preds(ModuleInfo1, PredTable, ModuleInfo).
%-----------------------------------------------------------------------------%
:- pred constraint__propagate_goal(hlds__goal, hlds__goal,
mode_info, mode_info).
:- mode constraint__propagate_goal(in, out,
mode_info_di, mode_info_uo) is det.
constraint__propagate_goal(Goal0 - GoalInfo, Goal - GoalInfo) -->
mode_info_dcg_get_instmap(InstMap0),
{ goal_info_get_instmap_delta(GoalInfo, DeltaInstMap) },
{ apply_instmap_delta(InstMap0, DeltaInstMap, InstMap) },
mode_info_set_instmap(InstMap),
constraint__propagate_goal_2(Goal0, Goal),
mode_info_set_instmap(InstMap).
%-----------------------------------------------------------------------------%
:- pred constraint__propagate_goal_2(hlds__goal_expr, hlds__goal_expr,
mode_info, mode_info).
:- mode constraint__propagate_goal_2(in, out,
mode_info_di, mode_info_uo) is det.
constraint__propagate_goal_2(conj(Goals0), conj(Goals)) -->
constraint__checkpoint(enter, "conj"),
constraint__propagate_conj(Goals0, Goals),
constraint__checkpoint(exit, "conj").
constraint__propagate_goal_2(disj(Goals0), disj(Goals)) -->
constraint__checkpoint(enter, "disj"),
constraint__propagate_disj(Goals0, Goals),
constraint__checkpoint(exit, "disj").
constraint__propagate_goal_2(switch(Var, Det, Cases0),
switch(Var, Det, Cases)) -->
constraint__checkpoint(enter, "switch"),
constraint__propagate_cases(Cases0, Cases),
constraint__checkpoint(exit, "switch").
constraint__propagate_goal_2(if_then_else(Vars, Cond0, Then0, Else0),
if_then_else(Vars, Cond, Then, Else)) -->
constraint__checkpoint(enter, "if_then_else"),
mode_info_dcg_get_instmap(InstMap0),
constraint__propagate_goal(Cond0, Cond),
% mode_info_dcg_get_instmap(InstMap1),
constraint__propagate_goal(Then0, Then),
mode_info_set_instmap(InstMap0),
constraint__propagate_goal(Else0, Else),
constraint__checkpoint(exit, "if_then_else").
constraint__propagate_goal_2(not(Goal0), not(Goal)) -->
constraint__checkpoint(enter, "not"),
constraint__propagate_goal(Goal0, Goal),
constraint__checkpoint(exit, "not").
constraint__propagate_goal_2(some(Vars, Goal0), some(Vars, Goal)) -->
constraint__checkpoint(enter, "some"),
constraint__propagate_goal(Goal0, Goal),
constraint__checkpoint(exit, "some").
constraint__propagate_goal_2(
call(PredId, ProcId, ArgVars, Builtin, Sym, Context, Follow),
call(PredId, ProcId, ArgVars, Builtin, Sym, Context, Follow)) -->
constraint__checkpoint(enter, "call"),
constraint__checkpoint(exit, "call").
constraint__propagate_goal_2(unify(A,B,C,D,E), unify(A,B,C,D,E)) -->
constraint__checkpoint(enter, "unify"),
constraint__checkpoint(exit, "unify").
constraint__propagate_goal_2(
pragma_c_code(C_Code, PredId, ProcId, Args, ArgNameMap),
pragma_c_code(C_Code, PredId, ProcId, Args, ArgNameMap)) -->
constraint__checkpoint(enter, "pragma_c_code"),
constraint__checkpoint(exit, "pragma_c_code").
%-----------------------------------------------------------------------------%
:- pred constraint__propagate_disj(list(hlds__goal), list(hlds__goal),
mode_info, mode_info).
:- mode constraint__propagate_disj(in, out,
mode_info_di, mode_info_uo) is det.
constraint__propagate_disj([], []) --> [].
constraint__propagate_disj([Goal0|Goals0], [Goal|Goals]) -->
mode_info_dcg_get_instmap(InstMap0),
constraint__propagate_goal(Goal0, Goal),
mode_info_set_instmap(InstMap0),
constraint__propagate_disj(Goals0, Goals).
%-----------------------------------------------------------------------------%
:- pred constraint__propagate_cases(list(case), list(case),
mode_info, mode_info).
:- mode constraint__propagate_cases(in, out,
mode_info_di, mode_info_uo) is det.
constraint__propagate_cases([], []) --> [].
constraint__propagate_cases([case(Cons, Goal0)|Goals0],
[case(Cons, Goal)|Goals]) -->
mode_info_dcg_get_instmap(InstMap0),
constraint__propagate_goal(Goal0, Goal),
mode_info_set_instmap(InstMap0),
constraint__propagate_cases(Goals0, Goals).
%-----------------------------------------------------------------------------%
% constraint__propagate_conj detects the constraints in
% a conjunction and moves them to as early as possible
% in the list.
:- pred constraint__propagate_conj(list(hlds__goal), list(hlds__goal),
mode_info, mode_info).
:- mode constraint__propagate_conj(in, out,
mode_info_di, mode_info_uo) is det.
constraint__propagate_conj(Goals0, Goals) -->
=(ModeInfo0),
{ mode_info_get_delay_info(ModeInfo0, DelayInfo0) },
{ delay_info__enter_conj(DelayInfo0, DelayInfo1) },
mode_info_set_delay_info(DelayInfo1),
% mode_info_add_goals_live_vars(Goals0),
mode_info_dcg_get_instmap(InstMap0),
constraint__find_constraints(Goals0, Goals1, Constraints1),
mode_info_set_instmap(InstMap0),
% constraint__distribute_constraints(Constraints1, Goals1, Goals),
{ list__append(Constraints1, Goals1, Goals2) },
transform__reschedule_conj(Goals2, Goals),
=(ModeInfo1),
{ mode_info_get_delay_info(ModeInfo1, DelayInfo2) },
{ delay_info__leave_conj(DelayInfo2, DelayedGoals, DelayInfo3) },
mode_info_set_delay_info(DelayInfo3),
( { DelayedGoals = [] } ->
[]
;
{ error("constraint__propagate_conj") }
).
:- pred constraint__find_constraints(list(hlds__goal), list(hlds__goal),
list(constraint), mode_info, mode_info).
:- mode constraint__find_constraints(in, out, out,
mode_info_di, mode_info_uo) is det.
constraint__find_constraints([], [], []) --> [].
constraint__find_constraints([Goal0 | Goals0], Goals, Constraints) -->
mode_info_dcg_get_instmap(InstMap0),
constraint__propagate_goal(Goal0, Goal1),
% mode_info_dcg_get_instmap(InstMap1),
{ Goal1 = Goal1Goal - Goal1Info },
( { Goal1Goal = conj(Goal1List) } ->
{ list__append(Goal1List, Goals0, Goals1) },
mode_info_set_instmap(InstMap0),
constraint__find_constraints(Goals1, Goals, Constraints)
;
constraint__find_constraints(Goals0, Goals1, Constraints0),
=(ModeInfo),
( { constraint__is_constraint(Goal1Info, ModeInfo) } ->
mode_info_write_string("Found constraint:\n"),
mode_info_write_goal(Goal1, 1),
mode_info_write_string("\n"),
{ Constraints = [Goal1 | Constraints0] },
{ Goals = Goals1 }
;
{ Constraints = Constraints0 },
{ Goals = [Goal1 | Goals1] }
)
).
%:- pred constraint__distribute_constraints(list(constraint), list(hlds__goal),
% list(hlds__goal), mode_info, mode_info).
%:- mode constraint__distribute_constraints(in, in, out,
% mode_info_di, mode_info_uo) is det.
%-----------------------------------------------------------------------------%
:- pred constraint__is_constraint(hlds__goal_info, mode_info).
:- mode constraint__is_constraint(in, mode_info_ui) is semidet.
constraint__is_constraint(GoalInfo, ModeInfo) :-
goal_info_get_determinism(GoalInfo, Det),
constraint__determinism(Det),
constraint__no_output_vars(GoalInfo, ModeInfo).
:- pred constraint__no_output_vars(hlds__goal_info, mode_info).
:- mode constraint__no_output_vars(in, mode_info_ui) is semidet.
constraint__no_output_vars(GoalInfo, ModeInfo) :-
goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
(
InstMapDelta = unreachable
;
InstMapDelta = reachable(InstMapDelta1),
mode_info_get_varset(ModeInfo, VarSet),
varset__vars(VarSet, VarList),
mode_info_get_module_info(ModeInfo, ModuleInfo),
mode_info_get_instmap(ModeInfo, InstMap),
constraint__no_output_vars_2(VarList, InstMap, InstMapDelta1,
ModuleInfo)
).
:- pred constraint__no_output_vars_2(list(var), instmap, instmapping,
module_info).
:- mode constraint__no_output_vars_2(in, in, in, in) is semidet.
constraint__no_output_vars_2([], _, _, _).
constraint__no_output_vars_2([Var | Vars], InstMap0, InstMapDelta,
ModuleInfo) :-
( map__search(InstMapDelta, Var, Inst) ->
instmap_lookup_var(InstMap0, Var, Inst0),
inst_matches_binding(Inst, Inst0, ModuleInfo)
;
true
),
constraint__no_output_vars_2(Vars, InstMap0, InstMapDelta, ModuleInfo).
% constraint__determinism(Det) is true iff Det is
% a possible determinism of a constraint. The
% determinisms which use a model_semi code model
% are obviously constraints. Should erroneous
% also be treated as a constraint?
:- pred constraint__determinism(determinism).
:- mode constraint__determinism(in) is semidet.
constraint__determinism(semidet).
constraint__determinism(failure).
% constraint__determinism(erroneous). % maybe
%-----------------------------------------------------------------------------%
:- type my_port
---> enter
; exit
; wakeup.
:- pred constraint__checkpoint(my_port, string, mode_info, mode_info).
:- mode constraint__checkpoint(in, in, mode_info_di, mode_info_uo) is det.
constraint__checkpoint(Port, Msg, ModeInfo0, ModeInfo) :-
mode_info_get_io_state(ModeInfo0, IOState0),
% globals__io_lookup_bool_option(debug_modes, DoCheckPoint,
% IOState0, IOState1),
IOState0 = IOState1,
( semidet_succeed ->
constraint__checkpoint_2(Port, Msg, ModeInfo0, IOState1, IOState)
;
IOState = IOState1
),
mode_info_set_io_state(ModeInfo0, IOState, ModeInfo).
:- pred is_bool(bool::in) is det.
is_bool(_).
:- pred constraint__checkpoint_2(my_port, string, mode_info, io__state, io__state).
:- mode constraint__checkpoint_2(in, in, mode_info_ui, di, uo) is det.
constraint__checkpoint_2(Port, Msg, ModeInfo) -->
{ mode_info_get_errors(ModeInfo, Errors) },
{ is_bool(Detail) }, % explicit type qualification needed to
% resolve type ambiguity
( { Port = enter } ->
io__write_string("Enter "),
{ Detail = yes }
; { Port = wakeup } ->
io__write_string("Wake "),
{ Detail = no }
; { Errors = [] } ->
io__write_string("Exit "),
{ Detail = yes }
;
io__write_string("Delay "),
{ Detail = no }
),
io__write_string(Msg),
( { Detail = yes } ->
io__write_string(":\n"),
globals__io_lookup_bool_option(statistics, Statistics),
maybe_report_stats(Statistics),
{ mode_info_get_instmap(ModeInfo, InstMap) },
( { InstMap = reachable(InstMapping) } ->
{ map__to_assoc_list(InstMapping, AssocList) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
constraint__write_var_insts(AssocList, VarSet, InstVarSet)
;
io__write_string("\tUnreachable\n")
)
;
[]
),
io__write_string("\n").
:- pred constraint__write_var_insts(assoc_list(var, inst), varset, varset,
io__state, io__state).
:- mode constraint__write_var_insts(in, in, in, di, uo) is det.
constraint__write_var_insts([], _, _) --> [].
constraint__write_var_insts([Var - Inst | VarInsts], VarSet, InstVarSet) -->
io__write_string("\t"),
mercury_output_var(Var, VarSet),
io__write_string(" :: "),
mercury_output_inst(Inst, InstVarSet),
( { VarInsts = [] } ->
[]
;
io__write_string("\n"),
constraint__write_var_insts(VarInsts, VarSet, InstVarSet)
).
%-----------------------------------------------------------------------------%
:- pred mode_info_write_string(string, mode_info, mode_info).
:- mode mode_info_write_string(in, mode_info_di, mode_info_uo) is det.
mode_info_write_string(Msg, ModeInfo0, ModeInfo) :-
mode_info_get_io_state(ModeInfo0, IOState0),
io__write_string(Msg, IOState0, IOState),
mode_info_set_io_state(ModeInfo0, IOState, ModeInfo).
:- pred mode_info_write_goal(hlds__goal, int, mode_info, mode_info).
:- mode mode_info_write_goal(in, in, mode_info_di, mode_info_uo) is det.
mode_info_write_goal(Goal, Indent, ModeInfo0, ModeInfo) :-
mode_info_get_io_state(ModeInfo0, IOState0),
% globals__io_lookup_bool_option(debug_modes, DoCheckPoint,
% IOState0, IOState1),
IOState0 = IOState1,
( semidet_succeed ->
mode_info_get_module_info(ModeInfo0, ModuleInfo),
mode_info_get_varset(ModeInfo0, VarSet),
hlds_out__write_goal(Goal, ModuleInfo, VarSet, Indent,
IOState1, IOState)
;
IOState = IOState1
),
mode_info_set_io_state(ModeInfo0, IOState, ModeInfo).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%