mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-21 12:23:44 +00:00
Since this is the first converted module that dumps out goals when
debugging trace flags are enabled, this required generalizing the code
that does that, to take either varsets or var_tables as a means of
specifying the names of variables. We do this via a new type,
var_name_source, which contains either a varset or a var_table.
Almost all of this diff is there to implement this generalization.
A large part of it affects code in the parse_tree package that we use
to write out the parts of HLDS goals that are defined by types defined
in that package. Since we want to avoid making any part of the parse_tree
package dependent on the hlds package, this required defining the
var_name_source type in the parse_tree package, which in turn requires
var_table.m to be in that same package.
compiler/lco.m:
Convert this module to use var_tables instead of varsets and vartypes.
compiler/var_table.m:
Move this module from the hlds package to the parse_tree package.
To make this, possible, move the parts that required access to the HLDS
to hlds_pred.m, from where it was usually invoked.
Export some utility predicates to allow the moved code to work
in hlds_pred.m without access to the actual definition of the
var_table type.
Define the var_name_source type.
Add some utility functions for use by code writing out variable names.
compiler/hlds_pred.m:
Add the code moved from var_table.m.
compiler/vartypes.m:
Move this module from the hlds package to the parse_tree package,
for symmetry with var_table.m. It did not depend on being in hlds
in any way.
compiler/hlds.m:
compiler/parse_tree.m:
Move vartypes.m and var_table.m from the hlds package
to the parse_tree package.
compiler/hlds_out_goal.m:
Change all the predicates in this module to take a var_name_source
instead of a prog_varset.
Fix some comments.
compiler/hlds_out_util.m:
Change some of the predicates in this module (those called from
hlds_out_goal.m) to take a var_name_source instead of a prog_varset.
compiler/parse_tree_out_term.m:
Provide variants of some existing predicates and functions that take
var_name_sources instead of varsets. The code of the copies
duplicates the logic of the originals, though I hope that this
duplication can be done away with at the end of the transition.
(The best solution would be to use a typeclass with methods
that convert vars to their names, but we would want to ensure
that the compiler can specialize all the affected predicates
and functions to the two instances of this typeclass, which is
something that we cannot do yet. In the meantime, the lack of
any generalization in the old versions preserves their performance.)
tools/sort_imports:
tools/filter_sort_imports:
A new tool that automatically sorts any occurrences of consecutive
":- import_module" declarations in the named files. The sorting is done
in filter_sort_imports; sort_imports loops over the named files.
After automatically replacing all occurrences of hlds.{vartypes,var_table}
in import_module declarations with their parse_tree versions, the updated
import_module declarations were usually out of order with respect to
their neighbours. I used this script to fix that, and some earlier
out-of-order imports.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_heap_ops.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_trail_ops.m:
compiler/analysis.m:
compiler/arg_info.m:
compiler/build_mode_constraints.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/check_promise.m:
compiler/closure_analysis.m:
compiler/closure_gen.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/common.m:
compiler/compile_target_code.m:
compiler/complexity.m:
compiler/const_prop.m:
compiler/constraint.m:
compiler/continuation_info.m:
compiler/convert_parse_tree.m:
compiler/coverage_profiling.m:
compiler/cse_detection.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.util.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/deforest.m:
compiler/delay_construct.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/det_util.m:
compiler/direct_arg_in_out.m:
compiler/disj_gen.m:
compiler/distance_granularity.m:
compiler/equiv_type_hlds.m:
compiler/exception_analysis.m:
compiler/file_names.m:
compiler/float_regs.m:
compiler/follow_vars.m:
compiler/format_call.m:
compiler/generate_dep_d_files.m:
compiler/get_dependencies.m:
compiler/goal_expr_to_goal.m:
compiler/goal_mode.m:
compiler/goal_path.m:
compiler/goal_store.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_clauses.m:
compiler/hlds_code_util.m:
compiler/hlds_error_util.m:
compiler/hlds_goal.m:
compiler/hlds_llds.m:
compiler/hlds_out_pred.m:
compiler/hlds_rtti.m:
compiler/hlds_statistics.m:
compiler/inlining.m:
compiler/inst_check.m:
compiler/inst_test.m:
compiler/inst_user.m:
compiler/instance_method_clauses.m:
compiler/instmap.m:
compiler/intermod.m:
compiler/intermod_analysis.m:
compiler/interval.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds.m:
compiler/llds_out_data.m:
compiler/llds_out_file.m:
compiler/llds_out_util.m:
compiler/lookup_switch.m:
compiler/loop_inv.m:
compiler/make.module_target.m:
compiler/make.util.m:
compiler/make_goal.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_types.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/middle_rec.m:
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_simplify_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_cs_class.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mmc_analysis.m:
compiler/mode_comparison.m:
compiler/mode_constraints.m:
compiler/mode_debug.m:
compiler/mode_errors.m:
compiler/mode_info.m:
compiler/mode_ordering.m:
compiler/modecheck_call.m:
compiler/modecheck_coerce.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/module_cmds.m:
compiler/old_type_constraints.m:
compiler/opt_debug.m:
compiler/optimize.m:
compiler/options_file.m:
compiler/ordering_mode_constraints.m:
compiler/par_loop_control.m:
compiler/parse_item.m:
compiler/parse_string_format.m:
compiler/parse_tree_out_inst.m:
compiler/parse_tree_to_term.m:
compiler/parse_util.m:
compiler/pd_debug.m:
compiler/pd_info.m:
compiler/pd_util.m:
compiler/peephole.m:
compiler/polymorphism.m:
compiler/polymorphism_info.m:
compiler/polymorphism_lambda.m:
compiler/polymorphism_type_class_info.m:
compiler/polymorphism_type_info.m:
compiler/post_typecheck.m:
compiler/pragma_c_gen.m:
compiler/pred_name.m:
compiler/pred_table.m:
compiler/prog_item.m:
compiler/prog_rep.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/push_goals_together.m:
compiler/qual_info.m:
compiler/quantification.m:
compiler/rbmm.execution_path.m:
compiler/rbmm.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.points_to_graph.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_resurrection_renaming.m:
compiler/rbmm.region_transformation.m:
compiler/recompilation.used_file.m:
compiler/recompilation.version.m:
compiler/recompute_instmap_deltas.m:
compiler/resolve_unify_functor.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/saved_vars.m:
compiler/set_of_var.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_conj.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/simplify_goal_scope.m:
compiler/simplify_goal_switch.m:
compiler/simplify_goal_unify.m:
compiler/simplify_info.m:
compiler/simplify_proc.m:
compiler/size_prof.m:
compiler/smm_common.m:
compiler/ssdebug.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/stack_opt.m:
compiler/stm_expand.m:
compiler/store_alloc.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.domain.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/superhomogeneous.m:
compiler/switch_detection.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_data.m:
compiler/term_constr_initial.m:
compiler/term_constr_main.m:
compiler/term_constr_main_types.m:
compiler/term_constr_util.m:
compiler/term_pass1.m:
compiler/term_traversal.m:
compiler/term_util.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/transform_llds.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/type_assign.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/typecheck_debug.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unify_gen_construct.m:
compiler/unify_gen_deconstruct.m:
compiler/unify_proc.m:
compiler/unique_modes.m:
compiler/unneeded_code.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/var_locn.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
619 lines
25 KiB
Mathematica
619 lines
25 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001-2012 The 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: mode_ordering.m.
|
|
% Main author: dmo.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module check_hlds.mode_ordering.
|
|
:- interface.
|
|
|
|
:- import_module check_hlds.mode_constraint_robdd.
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
|
|
:- type pred_constraint_info
|
|
---> pci(
|
|
pci_mode_constraint :: mode_constraint,
|
|
pci_mci :: mode_constraint_info
|
|
).
|
|
|
|
:- type pred_constraint_map == map(pred_id, pred_constraint_info).
|
|
|
|
% Given a top-down list of predicate SCCs, attempt to schedule goals
|
|
% for mode of each predicate, and determine which modes are needed
|
|
% for each predicate.
|
|
%
|
|
:- pred mode_ordering(pred_constraint_map::in, list(list(pred_id))::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.clause_to_proc.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.inst_graph.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.goal_path.
|
|
:- import_module mode_robdd.
|
|
:- import_module mode_robdd.tfeirn.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.set_of_var.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module digraph.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module solutions.
|
|
:- import_module stack.
|
|
|
|
mode_ordering(PredConstraintMap, SCCs, !ModuleInfo, !IO) :-
|
|
list.foldl(mode_ordering_scc(PredConstraintMap), SCCs, !ModuleInfo),
|
|
report_ordering_mode_errors(!.ModuleInfo, !IO).
|
|
|
|
:- pred mode_ordering_scc(pred_constraint_map::in, list(pred_id)::in,
|
|
module_info::in, module_info::out) is det.
|
|
|
|
mode_ordering_scc(PredConstraintMap, SCC, !ModuleInfo) :-
|
|
% XXX This call to copy_clauses_to_procs_for_preds_in_module_info
|
|
% should *not* be necessary.
|
|
copy_clauses_to_nonmethod_procs_for_preds_in_module_info(SCC, !ModuleInfo),
|
|
list.foldl(mode_ordering_pred(PredConstraintMap, SCC), SCC, !ModuleInfo).
|
|
|
|
:- pred mode_ordering_pred(pred_constraint_map::in, list(pred_id)::in,
|
|
pred_id::in, module_info::in, module_info::out) is det.
|
|
|
|
mode_ordering_pred(PredConstraintMap, _SCC, PredId, !ModuleInfo) :-
|
|
% XXX Mode inference NYI.
|
|
RequestedProcsMap0 = map.init,
|
|
|
|
module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
|
|
lookup_pred_constraint(PredConstraintMap, PredId, ModeConstraint0, MCI),
|
|
( if pred_info_infer_modes(PredInfo0) then
|
|
( if map.search(RequestedProcsMap0, PredId, RequestedProcs) then
|
|
list.foldl(
|
|
mode_ordering_infer_proc(!.ModuleInfo, PredConstraintMap,
|
|
PredId, MCI, ModeConstraint0),
|
|
RequestedProcs, PredInfo0, PredInfo)
|
|
else
|
|
% XXX Maybe we should remove the predicate from the
|
|
% module_info here since it is not used.
|
|
PredInfo = PredInfo0
|
|
)
|
|
else
|
|
ProcIds = pred_info_all_non_imported_procids(PredInfo0),
|
|
list.foldl(
|
|
mode_ordering_check_proc(!.ModuleInfo, PredConstraintMap,
|
|
PredId, MCI, ModeConstraint0),
|
|
ProcIds, PredInfo0, PredInfo)
|
|
),
|
|
module_info_set_pred_info(PredId, PredInfo, !ModuleInfo).
|
|
|
|
:- pred mode_ordering_infer_proc(module_info::in, pred_constraint_map::in,
|
|
pred_id::in, mode_constraint_info::in,
|
|
mode_constraint::in, mode_constraint::in,
|
|
pred_info::in, pred_info::out) is det.
|
|
|
|
mode_ordering_infer_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
|
|
Constraint0, ModeDeclConstraint, !PredInfo) :-
|
|
pred_info_create_proc_info_for_mode_decl_constraint(ModeDeclConstraint,
|
|
ProcId, !PredInfo),
|
|
mode_ordering_check_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
|
|
Constraint0, ProcId, !PredInfo).
|
|
|
|
:- pred mode_ordering_check_proc(module_info::in, pred_constraint_map::in,
|
|
pred_id::in, mode_constraint_info::in, mode_constraint::in, proc_id::in,
|
|
pred_info::in, pred_info::out) is det.
|
|
|
|
mode_ordering_check_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
|
|
Constraint0, ProcId, !PredInfo) :-
|
|
pred_info_proc_info(!.PredInfo, ProcId, ProcInfo0),
|
|
proc_info_head_modes_constraint(ProcInfo0, ModeDeclConstraint),
|
|
Constraint = Constraint0 * ModeDeclConstraint,
|
|
pred_info_get_inst_graph_info(!.PredInfo, InstGraphInfo),
|
|
InstGraph = InstGraphInfo ^ implementation_inst_graph,
|
|
mode_ordering_proc(ModuleInfo, PredConstraintMap, PredId, MCI, InstGraph,
|
|
Constraint, ProcInfo0, ProcInfo),
|
|
pred_info_set_proc_info(ProcId, ProcInfo, !PredInfo).
|
|
|
|
% Perform mode ordering for a procedure. The ModeConstraint must be
|
|
% constrained to contain just the mode information for this procedure.
|
|
%
|
|
:- pred mode_ordering_proc(module_info::in, pred_constraint_map::in,
|
|
pred_id::in, mode_constraint_info::in, inst_graph::in,
|
|
mode_constraint::in, proc_info::in, proc_info::out) is det.
|
|
|
|
mode_ordering_proc(ModuleInfo, PredConstraintMap, PredId, MCI, InstGraph,
|
|
ModeConstraint, !ProcInfo) :-
|
|
ProdVarsMap = atomic_prodvars_map(ModeConstraint, MCI),
|
|
LambdaNesting0 = stack.init,
|
|
get_forward_goal_path_map_for_pred(MCI, PredId, ForwardGoalPathMap),
|
|
MOI0 = mode_ordering_info(InstGraph, ProdVarsMap, LambdaNesting0,
|
|
ModuleInfo, PredConstraintMap, ForwardGoalPathMap),
|
|
|
|
proc_info_get_goal(!.ProcInfo, Goal0),
|
|
mode_order_goal(Goal0, Goal, MOI0, _MOI),
|
|
proc_info_set_goal(Goal, !ProcInfo).
|
|
|
|
:- type mode_ordering_info
|
|
---> mode_ordering_info(
|
|
moi_inst_graph :: inst_graph,
|
|
moi_prodvars_map :: prodvars_map,
|
|
moi_lambda_nesting :: lambda_path,
|
|
moi_module_info :: module_info,
|
|
moi_pred_constraint_map :: pred_constraint_map,
|
|
moi_goal_path_map :: goal_forward_path_map
|
|
).
|
|
|
|
:- pred enter_lambda_goal(goal_id::in,
|
|
mode_ordering_info::in, mode_ordering_info::out) is det.
|
|
|
|
enter_lambda_goal(GoalId, !MOI) :-
|
|
LambdaNesting0 = !.MOI ^ moi_lambda_nesting,
|
|
!MOI ^ moi_lambda_nesting := stack.push(LambdaNesting0, GoalId).
|
|
|
|
:- pred leave_lambda_goal(mode_ordering_info::in, mode_ordering_info::out)
|
|
is det.
|
|
|
|
leave_lambda_goal(!MOI) :-
|
|
LambdaNesting0 = !.MOI ^ moi_lambda_nesting,
|
|
stack.det_pop(_, LambdaNesting0, LambdaNesting),
|
|
!MOI ^ moi_lambda_nesting := LambdaNesting.
|
|
|
|
:- pred mode_order_goal(hlds_goal::in, hlds_goal::out,
|
|
mode_ordering_info::in, mode_ordering_info::out) is det.
|
|
|
|
mode_order_goal(Goal0, Goal, !MOI) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
mode_order_goal_2(GoalExpr0, GoalExpr, GoalInfo0, GoalInfo, !MOI),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo).
|
|
|
|
:- pred mode_order_goal_2(hlds_goal_expr::in, hlds_goal_expr::out,
|
|
hlds_goal_info::in, hlds_goal_info::out,
|
|
mode_ordering_info::in, mode_ordering_info::out) is det.
|
|
|
|
mode_order_goal_2(GoalExpr0, GoalExpr, !GoalInfo, !MOI) :-
|
|
(
|
|
GoalExpr0 = conj(ConjType, Goals0),
|
|
(
|
|
ConjType = plain_conj,
|
|
list.map_foldl(mode_order_goal, Goals0, Goals1, !MOI),
|
|
ForwardGoalPathMap = !.MOI ^ moi_goal_path_map,
|
|
mode_order_conj(ForwardGoalPathMap, Goals1, Goals),
|
|
union_mode_vars_sets(Goals, !GoalInfo),
|
|
ConsVars = !.GoalInfo ^ consuming_vars,
|
|
!GoalInfo ^ consuming_vars :=
|
|
ConsVars `set_of_var.difference` !.GoalInfo ^ producing_vars,
|
|
NeedVars = !.GoalInfo ^ need_visible_vars,
|
|
!GoalInfo ^ need_visible_vars :=
|
|
NeedVars `set_of_var.difference` !.GoalInfo ^ make_visible_vars
|
|
;
|
|
ConjType = parallel_conj,
|
|
list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
|
|
union_mode_vars_sets(Goals, !GoalInfo)
|
|
),
|
|
GoalExpr = conj(ConjType, Goals)
|
|
;
|
|
GoalExpr0 = plain_call(PredId, _, Args, _, _, _),
|
|
set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
|
|
MakeVisibleVars =
|
|
set_of_var.list_to_set(Args) `set_of_var.intersect` ProdVars,
|
|
|
|
find_matching_proc(PredId, Args, ProdVars, ProcId, ConsumingVars,
|
|
!MOI),
|
|
NeedVisibleVars =
|
|
set_of_var.list_to_set(Args) `set_of_var.intersect` ConsumingVars,
|
|
|
|
goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
|
|
goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
|
|
goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo),
|
|
GoalExpr = GoalExpr0 ^ call_proc_id := ProcId
|
|
;
|
|
GoalExpr0 = generic_call(_GenericCall0, _Args, _Modes0, _, _Det),
|
|
unexpected($pred, "generic_call NYI")
|
|
;
|
|
GoalExpr0 = switch(_Var, _CanFail0, _Cases0),
|
|
unexpected($pred, "switch")
|
|
;
|
|
GoalExpr0 = unify(VarA, RHS0, UnifyMode, Unification0, Context),
|
|
set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
|
|
InstGraph = !.MOI ^ moi_inst_graph,
|
|
(
|
|
RHS0 = rhs_var(VarB),
|
|
RHS = RHS0,
|
|
( if set_of_var.contains(ProdVars, VarA) then
|
|
Unification = assign(VarA, VarB),
|
|
MakeVisibleVars = set_of_var.make_singleton(VarA),
|
|
NeedVisibleVars = set_of_var.make_singleton(VarB)
|
|
else if set_of_var.contains(ProdVars, VarB) then
|
|
Unification = assign(VarB, VarA),
|
|
MakeVisibleVars = set_of_var.make_singleton(VarB),
|
|
NeedVisibleVars = set_of_var.make_singleton(VarA)
|
|
else
|
|
Unification = simple_test(VarA, VarB),
|
|
% XXX may be complicated unify -- need to check.
|
|
MakeVisibleVars = set_of_var.init,
|
|
NeedVisibleVars = set_of_var.list_to_set([VarA, VarB])
|
|
),
|
|
ConsumingVarsList = solutions.solutions(
|
|
( pred(Var::out) is nondet :-
|
|
inst_graph.same_graph_corresponding_nodes(InstGraph,
|
|
VarA, VarB, VarC, VarD),
|
|
( if set_of_var.contains(ProdVars, VarC) then
|
|
Var = VarD
|
|
else if set_of_var.contains(ProdVars, VarD) then
|
|
Var = VarC
|
|
else
|
|
fail
|
|
)
|
|
)
|
|
),
|
|
ConsumingVars = set_of_var.sorted_list_to_set(ConsumingVarsList)
|
|
;
|
|
RHS0 = rhs_functor(_ConsId, _IsExistConstruct, ArgVars),
|
|
RHS = RHS0,
|
|
( if set_of_var.contains(ProdVars, VarA) then
|
|
% Unification = construct(VarA, ConsId, ArgVars,
|
|
% _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
|
|
Unification = Unification0, % XXX
|
|
ConsumingVars = set_of_var.init,
|
|
MakeVisibleVars = set_of_var.list_to_set([VarA | ArgVars]),
|
|
NeedVisibleVars = set_of_var.init
|
|
else
|
|
% Unification = deconstruct(VarA, ConsId, ArgVars,
|
|
% _UniModes, _CanFail, _CanCGC),
|
|
Unification = Unification0, % XXX
|
|
ConsumingVars = set_of_var.make_singleton(VarA),
|
|
MakeVisibleVars = set_of_var.list_to_set(ArgVars),
|
|
NeedVisibleVars = set_of_var.make_singleton(VarA)
|
|
)
|
|
;
|
|
% Unification = construct(VarA, _ConsId, _ArgVars,
|
|
% _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
|
|
Unification = Unification0, % XXX
|
|
RHS0 = rhs_lambda_goal(A, B, C, D, NonLocals, ArgVarsModes0,
|
|
H, SubGoal0),
|
|
ArgVarsModes = ArgVarsModes0, % XXX
|
|
RHS = rhs_lambda_goal(A, B, C, D, NonLocals, ArgVarsModes,
|
|
H, SubGoal),
|
|
|
|
GoalId = goal_info_get_goal_id(!.GoalInfo),
|
|
enter_lambda_goal(GoalId, !MOI),
|
|
mode_order_goal(SubGoal0, SubGoal, !MOI),
|
|
leave_lambda_goal(!MOI),
|
|
|
|
ConsumingVarsList = solutions.solutions(
|
|
inst_graph.reachable_from_list(InstGraph, NonLocals)),
|
|
ConsumingVars = set_of_var.sorted_list_to_set(ConsumingVarsList),
|
|
MakeVisibleVars = set_of_var.make_singleton(VarA),
|
|
NeedVisibleVars = set_of_var.list_to_set(NonLocals)
|
|
),
|
|
goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
|
|
goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
|
|
goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo),
|
|
|
|
GoalExpr = unify(VarA, RHS, UnifyMode, Unification, Context)
|
|
;
|
|
GoalExpr0 = disj(Goals0),
|
|
list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
|
|
mode_order_disj(Goals, !GoalInfo),
|
|
GoalExpr = disj(Goals)
|
|
;
|
|
GoalExpr0 = negation(SubGoal0),
|
|
mode_order_goal(SubGoal0, SubGoal, !MOI),
|
|
goal_info_copy_mode_var_sets(SubGoal ^ hg_info, !GoalInfo),
|
|
GoalExpr = negation(SubGoal)
|
|
;
|
|
% XXX We should special-case the handling of from_ground_term_construct
|
|
% scopes.
|
|
GoalExpr0 = scope(Reason, SubGoal0),
|
|
mode_order_goal(SubGoal0, SubGoal, !MOI),
|
|
goal_info_copy_mode_var_sets(SubGoal ^ hg_info, !GoalInfo),
|
|
GoalExpr = scope(Reason, SubGoal)
|
|
;
|
|
GoalExpr0 = if_then_else(Locals, Cond0, Then0, Else0),
|
|
mode_order_goal(Cond0, Cond, !MOI),
|
|
mode_order_goal(Then0, Then, !MOI),
|
|
mode_order_goal(Else0, Else, !MOI),
|
|
% XXX Ned to make sure that Cond can be scheduled before Then and Else.
|
|
|
|
union_mode_vars_sets([Cond, Then], !GoalInfo),
|
|
ConsVars = !.GoalInfo ^ consuming_vars,
|
|
!GoalInfo ^ consuming_vars :=
|
|
ConsVars `set_of_var.difference` !.GoalInfo ^ producing_vars,
|
|
NeedVars = !.GoalInfo ^ need_visible_vars,
|
|
!GoalInfo ^ need_visible_vars :=
|
|
NeedVars `set_of_var.difference` !.GoalInfo ^ make_visible_vars,
|
|
|
|
combine_mode_vars_sets(Else ^ hg_info, !GoalInfo),
|
|
GoalExpr = if_then_else(Locals, Cond, Then, Else)
|
|
;
|
|
GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _),
|
|
unexpected($pred, "pragma_foreign_code NYI")
|
|
;
|
|
GoalExpr0 = shorthand(_),
|
|
unexpected($pred, "shorthand")
|
|
).
|
|
% mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
|
|
% Goal0 = atomic_goal(GoalType, Outer, Inner, Vars, MainGoal0,
|
|
% OrElseGoals0),
|
|
% mode_order_goal(MainGoal0, MainGoal, !MOI),
|
|
% list.map_foldl(mode_order_goal, OrElseGoals0, OrElseGoals, !MOI),
|
|
% mode_order_disj(OrElseGoals, !GoalInfo),
|
|
% Goal = atomic_goal(GoalType, Outer, Inner, Vars, MainGoal, OrElseGoals).
|
|
|
|
:- pred mode_order_disj(hlds_goals::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
mode_order_disj([], !GoalInfo).
|
|
mode_order_disj([hlds_goal(_, GI) | Goals], !GoalInfo) :-
|
|
goal_info_copy_mode_var_sets(GI, !GoalInfo),
|
|
list.foldl(mode_order_disj_2, Goals, !GoalInfo).
|
|
|
|
:- pred mode_order_disj_2(hlds_goal::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
mode_order_disj_2(hlds_goal(_, GI), !GoalInfo) :-
|
|
combine_mode_vars_sets(GI, !GoalInfo).
|
|
|
|
:- pred combine_mode_vars_sets(hlds_goal_info::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
combine_mode_vars_sets(GI, !GoalInfo) :-
|
|
ProdVars0 = !.GoalInfo ^ producing_vars,
|
|
ConsumVars0 = !.GoalInfo ^ consuming_vars,
|
|
MakeVisibleVars0 = !.GoalInfo ^ make_visible_vars,
|
|
NeedVisibleVars0 = !.GoalInfo ^ need_visible_vars,
|
|
|
|
!GoalInfo ^ producing_vars
|
|
:= ProdVars0 `set_of_var.intersect` GI ^ producing_vars,
|
|
!GoalInfo ^ consuming_vars
|
|
:= ConsumVars0 `set_of_var.union` GI ^ consuming_vars,
|
|
!GoalInfo ^ make_visible_vars
|
|
:= MakeVisibleVars0 `set_of_var.intersect` GI ^ make_visible_vars,
|
|
!GoalInfo ^ need_visible_vars
|
|
:= NeedVisibleVars0 `set_of_var.union` GI ^ need_visible_vars.
|
|
|
|
:- pred union_mode_vars_sets(hlds_goals::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
union_mode_vars_sets(Goals, !GoalInfo) :-
|
|
list.foldl(union_mode_vars_set, Goals, !GoalInfo).
|
|
|
|
:- pred union_mode_vars_set(hlds_goal::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
union_mode_vars_set(Goal, !GoalInfo) :-
|
|
ProdVars0 = !.GoalInfo ^ producing_vars,
|
|
ConsumVars0 = !.GoalInfo ^ consuming_vars,
|
|
MakeVisibleVars0 = !.GoalInfo ^ make_visible_vars,
|
|
NeedVisibleVars0 = !.GoalInfo ^ need_visible_vars,
|
|
Goal = hlds_goal(_, GI),
|
|
|
|
!GoalInfo ^ producing_vars
|
|
:= ProdVars0 `set_of_var.union` GI ^ producing_vars,
|
|
!GoalInfo ^ consuming_vars
|
|
:= ConsumVars0 `union` GI ^ consuming_vars,
|
|
!GoalInfo ^ make_visible_vars
|
|
:= MakeVisibleVars0 `set_of_var.union` GI ^ make_visible_vars,
|
|
!GoalInfo ^ need_visible_vars
|
|
:= NeedVisibleVars0 `set_of_var.union` GI ^ need_visible_vars.
|
|
|
|
:- pred goal_info_copy_mode_var_sets(hlds_goal_info::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
goal_info_copy_mode_var_sets(GI, !GoalInfo) :-
|
|
!GoalInfo ^ producing_vars := GI ^ producing_vars,
|
|
!GoalInfo ^ consuming_vars := GI ^ consuming_vars,
|
|
!GoalInfo ^ make_visible_vars := GI ^ make_visible_vars,
|
|
!GoalInfo ^ need_visible_vars := GI ^ need_visible_vars.
|
|
|
|
:- pred mode_order_conj(goal_forward_path_map::in,
|
|
hlds_goals::in, hlds_goals::out) is det.
|
|
|
|
mode_order_conj(ForwardGoalPathMap, Goals0, Goals) :-
|
|
GoalMap = list.foldl(
|
|
( func(G, GM) = map.det_insert(GM, Index, G) :-
|
|
G = hlds_goal(_, GI),
|
|
GoalId = goal_info_get_goal_id(GI),
|
|
map.lookup(ForwardGoalPathMap, GoalId, GoalPath),
|
|
( if
|
|
goal_path_get_last(GoalPath, LastStep),
|
|
LastStep = step_conj(Index0)
|
|
then
|
|
Index = Index0
|
|
else
|
|
unexpected($pred, "goal_path error")
|
|
)
|
|
), Goals0, map.init),
|
|
|
|
ProdMap =
|
|
map.foldl(
|
|
( func(I, G, PM0) =
|
|
list.foldl(
|
|
(func(V, PM1) = map.det_insert(PM1, V, I)),
|
|
set_of_var.to_sorted_list(G ^ hg_info ^ producing_vars),
|
|
PM0)
|
|
), GoalMap, map.init),
|
|
|
|
MakeVisMap =
|
|
map.foldl(
|
|
( func(I, G, MVM0) =
|
|
list.foldl(
|
|
(func(V, MVM1) = map.set(MVM1, V, I)),
|
|
% XXX disjunction required!
|
|
set_of_var.to_sorted_list(G ^ hg_info ^ make_visible_vars),
|
|
MVM0)
|
|
), GoalMap, map.init),
|
|
|
|
Graph = map.foldl(
|
|
( func(I, G, !.R) = !:R :-
|
|
GI = G ^ hg_info,
|
|
digraph.add_vertex(I, Key0, !R),
|
|
!:R = list.foldl(
|
|
(func(V, !.R1) = !:R1 :-
|
|
( if Index1 = map.search(ProdMap, V) then
|
|
digraph.add_vertex(Index1, Key1, !R1),
|
|
digraph.add_edge(Key1, Key0, !R1)
|
|
else
|
|
true
|
|
)
|
|
), set_of_var.to_sorted_list(GI ^ consuming_vars), !.R),
|
|
!:R = list.foldl(
|
|
( func(V, !.R2) = !:R2 :-
|
|
( if Index2 = map.search(MakeVisMap, V) then
|
|
digraph.add_vertex(Index2, Key2, !R2),
|
|
digraph.add_edge(Key2, Key0, !R2)
|
|
else
|
|
true
|
|
)
|
|
), set_of_var.to_sorted_list(GI ^ need_visible_vars), !.R)
|
|
), GoalMap, digraph.init),
|
|
|
|
( if digraph.tsort(Graph, TSort) then
|
|
Goals = map.apply_to_list(TSort, GoalMap)
|
|
else
|
|
% XXX Report a mode error for this.
|
|
unexpected($pred, "tsort failed")
|
|
).
|
|
|
|
:- pred set_atomic_prod_vars(set_of_progvar::out,
|
|
hlds_goal_info::in, hlds_goal_info::out,
|
|
mode_ordering_info::in, mode_ordering_info::out) is det.
|
|
|
|
set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI) :-
|
|
LambdaNesting = !.MOI ^ moi_lambda_nesting,
|
|
AtomicProdVars = !.MOI ^ moi_prodvars_map,
|
|
GoalId = goal_info_get_goal_id(!.GoalInfo),
|
|
( if
|
|
map.search(AtomicProdVars, stack.push(LambdaNesting, GoalId),
|
|
ProdVars0)
|
|
then
|
|
ProdVars = ProdVars0
|
|
else
|
|
ProdVars = set_of_var.init
|
|
),
|
|
goal_info_set_producing_vars(ProdVars, !GoalInfo).
|
|
|
|
:- pred pred_info_create_proc_info_for_mode_decl_constraint(
|
|
mode_constraint::in, proc_id::out, pred_info::in, pred_info::out) is det.
|
|
|
|
pred_info_create_proc_info_for_mode_decl_constraint(_ModeDeclConstraint,
|
|
ProcId, !PredInfo) :-
|
|
( if semidet_succeed then
|
|
% XXX
|
|
sorry($pred, "NYI")
|
|
else
|
|
% XXX keep det checker happy.
|
|
ProcId = initial_proc_id
|
|
).
|
|
|
|
:- pred find_matching_proc(pred_id::in, list(prog_var)::in, set_of_progvar::in,
|
|
proc_id::out, set_of_progvar::out,
|
|
mode_ordering_info::in, mode_ordering_info::out) is det.
|
|
|
|
find_matching_proc(PredId, Args, ProdVars, ProcId, ConsumingVars, !MOI) :-
|
|
ModuleInfo = !.MOI ^ moi_module_info,
|
|
CallerInstGraph = !.MOI ^ moi_inst_graph,
|
|
PredConstraintMap = !.MOI ^ moi_pred_constraint_map,
|
|
lookup_pred_constraint(PredConstraintMap, PredId, _, MCInfo),
|
|
|
|
module_info_pred_info(ModuleInfo, PredId, PredInfo),
|
|
pred_info_get_inst_graph_info(PredInfo, CalleeInstGraphInfo),
|
|
CalleeInstGraph = CalleeInstGraphInfo ^ interface_inst_graph,
|
|
pred_info_get_proc_table(PredInfo, ProcTable),
|
|
map.to_assoc_list(ProcTable, ProcList),
|
|
( if
|
|
find_matching_proc_2(ProcList, ProdVars, Args,
|
|
CallerInstGraph, CalleeInstGraph, MCInfo, ProcId0, ConsumingVars0)
|
|
then
|
|
ProcId = ProcId0,
|
|
ConsumingVars = ConsumingVars0
|
|
else if
|
|
pred_info_infer_modes(PredInfo)
|
|
then
|
|
% XXX We are inferring modes for the called predicate. Need to add
|
|
% a new mode to the requested procs map.
|
|
unexpected($pred, "infer_modes NYI")
|
|
else
|
|
% If we get here, it means there is a mode error which should have been
|
|
% picked up by the constraints pass but was missed some how.
|
|
unexpected($pred, "unexpected mode error")
|
|
).
|
|
|
|
:- pred find_matching_proc_2(assoc_list(proc_id, proc_info)::in,
|
|
set_of_progvar::in, list(prog_var)::in, inst_graph::in, inst_graph::in,
|
|
mode_constraint_info::in, proc_id::out, set_of_progvar::out) is semidet.
|
|
|
|
find_matching_proc_2([ProcId0 - ProcInfo | ProcList], ProdVars, Args,
|
|
CallerInstGraph, CalleeInstGraph, MCInfo, ProcId, ConsumingVars) :-
|
|
proc_info_get_headvars(ProcInfo, HeadVars),
|
|
proc_info_head_modes_constraint(ProcInfo, Constraint0),
|
|
Constraint = ensure_normalised(Constraint0),
|
|
( if
|
|
(
|
|
all [X, Y] (
|
|
inst_graph.corresponding_nodes_from_lists(
|
|
CallerInstGraph, CalleeInstGraph, Args, HeadVars, X, Y)
|
|
)
|
|
=>
|
|
(
|
|
set_of_var.contains(ProdVars, X)
|
|
<=>
|
|
(
|
|
var_entailed(Constraint,
|
|
mode_constraint_var(MCInfo, out(Y))),
|
|
not var_entailed(Constraint,
|
|
mode_constraint_var(MCInfo, in(Y)))
|
|
)
|
|
)
|
|
)
|
|
then
|
|
ProcId = ProcId0,
|
|
GenPred =
|
|
( pred(X::out) is nondet :-
|
|
some [Y] (
|
|
inst_graph.corresponding_nodes_from_lists(CallerInstGraph,
|
|
CalleeInstGraph, Args, HeadVars, X, Y),
|
|
var_entailed(Constraint,
|
|
mode_constraint_var(MCInfo, in(Y)))
|
|
)
|
|
),
|
|
ConsumingVarsList = solutions.solutions(GenPred),
|
|
set_of_var.sorted_list_to_set(ConsumingVarsList, ConsumingVars)
|
|
else
|
|
find_matching_proc_2(ProcList, ProdVars, Args, CallerInstGraph,
|
|
CalleeInstGraph, MCInfo, ProcId, ConsumingVars)
|
|
).
|
|
|
|
:- pred report_ordering_mode_errors(module_info::in, io::di, io::uo) is det.
|
|
|
|
report_ordering_mode_errors(_, !IO).
|
|
% XXX
|
|
% io.stderr_stream(StdErr, !IO),
|
|
% io.write_string(StdErr, "Mode error reporting NYI", !IO).
|
|
|
|
:- pred lookup_pred_constraint(pred_constraint_map::in, pred_id::in,
|
|
mode_constraint::out, mode_constraint_info::out) is det.
|
|
|
|
lookup_pred_constraint(PCM, PredId, MC, MCI) :-
|
|
map.lookup(PCM, PredId, pci(MC, MCI)).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module check_hlds.mode_ordering.
|
|
%-----------------------------------------------------------------------------%
|