Files
mercury/compiler/modes.m
Fergus Henderson 30baaf2e45 Added predicate varset__vars.
varset.nl:
	Added predicate varset__vars.

term.nl:
	Added predicate term__vars_list.

typecheck.nl:
	Implement two previously unimplemented parts of the typechecker:
	detect attempts to instantiate type variables which occur in
	the predicate's type declaration, and detect any failure to
	bind all other type variables.  (That was the last two;
	apart from

prog_util.nl:
	Fix problem where the expansion of equivalence types was
	introducing fresh variables into the type varset, which caused
	problems in relation to the above changes to typecheck.nl.

hlds_out.nl:
	Fix typo in type declaration (found by above fixes to typechecker).

options.nl:
	Fix bug in type definition introduced by last change.

make_hlds.nl:
	Add a missing pred & mode declaration.

modes.nl:
	Don't display the verbose messages unless the very-verbose
	flag was specified.
1994-03-11 18:57:16 +00:00

1891 lines
66 KiB
Mathematica

%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
% File: modes.nl.
% Main author: fjh.
%
% This file contains a mode-checker.
% Adapted from the mode-checker; still very incomplete.
%
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module modes.
:- interface.
:- import_module hlds, io, prog_io.
:- pred modecheck(module_info, module_info, bool, io__state, io__state).
:- mode modecheck(input, output, output, di, uo).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module list, map, varset, prog_out, string, require, std_util.
:- import_module globals, getopt, options.
%-----------------------------------------------------------------------------%
% XXX need to pass FoundError to all steps
modecheck(Module0, Module, FoundError) -->
lookup_option(very_verbose, bool(VeryVerbose)),
lookup_option(verbose, bool(Verbose)),
io__stderr_stream(StdErr),
io__set_output_stream(StdErr, OldStream),
maybe_report_stats(VeryVerbose),
maybe_write_string(Verbose,
"% Checking for undefined insts and modes...\n"),
check_undefined_modes(Module0, Module1),
maybe_report_stats(VeryVerbose),
maybe_write_string(Verbose, "% Mode-checking clauses...\n"),
check_pred_modes(Module1, Module, FoundError),
maybe_report_stats(VeryVerbose),
io__set_output_stream(OldStream, _).
/*****
{ FoundError = no },
{ Module = Module1 },
*****/
%-----------------------------------------------------------------------------%
% Mode-check the code for all the predicates in a module.
:- pred check_pred_modes(module_info, module_info, bool, io__state, io__state).
:- mode check_pred_modes(input, output, output, di, uo).
check_pred_modes(Module0, Module, FoundError) -->
{ moduleinfo_predids(Module0, PredIds) },
modecheck_pred_modes_2(PredIds, Module0, no, Module, FoundError).
%-----------------------------------------------------------------------------%
% Iterate over the list of pred_ids in a module.
:- pred modecheck_pred_modes_2(list(pred_id), module_info, bool,
module_info, bool, io__state, io__state).
:- mode modecheck_pred_modes_2(input, input, input, output, output, di, uo).
modecheck_pred_modes_2([], ModuleInfo, Error, ModuleInfo, Error) --> [].
modecheck_pred_modes_2([PredId | PredIds], ModuleInfo0, Error0,
ModuleInfo, Error) -->
{ moduleinfo_preds(ModuleInfo0, Preds0) },
{ map__search(Preds0, PredId, PredInfo0) },
{ predinfo_clauses_info(PredInfo0, ClausesInfo0) },
{ ClausesInfo0 = clauses_info(_, _, _, Clauses0) },
( { Clauses0 = [] } ->
{ ModuleInfo1 = ModuleInfo0 }
;
lookup_option(very_verbose, bool(VeryVerbose)),
( { VeryVerbose = yes } ->
io__write_string("% Mode-checking predicate "),
write_pred_id(PredId),
io__write_string("\n")
;
[]
),
{ copy_clauses_to_procs(PredInfo0, PredInfo) },
{ map__set(Preds0, PredId, PredInfo, Preds) },
{ moduleinfo_set_preds(ModuleInfo0, Preds, ModuleInfo1) }
),
/******
% XXX fix here
{ predinfo_argmodes(PredInfo1, ModeVarSet, ArgModes) },
modecheck_clause_list(Clauses0, PredId, ModeVarSet, ArgModes,
ModuleInfo0, Error0, Clauses, Error1),
*****/
{ Error1 = Error0 },
modecheck_pred_modes_2(PredIds, ModuleInfo1, Error1, ModuleInfo, Error).
%-----------------------------------------------------------------------------%
:- pred copy_clauses_to_procs(pred_info, pred_info).
:- mode copy_clauses_to_procs(input, output).
copy_clauses_to_procs(PredInfo0, PredInfo) :-
predinfo_clauses_info(PredInfo0, ClausesInfo),
predinfo_procedures(PredInfo0, Procs0),
map__keys(Procs0, ProcIds),
copy_clauses_to_procs_2(ProcIds, ClausesInfo, Procs0, Procs),
predinfo_set_procedures(PredInfo0, Procs, PredInfo).
:- pred copy_clauses_to_procs_2(list(proc_id)::in, clauses_info::in,
proc_table::in, proc_table::out).
copy_clauses_to_procs_2([], _, Procs, Procs).
copy_clauses_to_procs_2([ProcId | ProcIds], ClausesInfo, Procs0, Procs) :-
ClausesInfo = clauses_info(VarSet, VarTypes, HeadVars, Clauses),
select_matching_clauses(Clauses, ProcId, MatchingClauses),
get_clause_goals(MatchingClauses, GoalList),
(GoalList = [SingleGoal] ->
Goal = SingleGoal
;
goalinfo_init(GoalInfo),
Goal = disj(GoalList) - GoalInfo
),
map__lookup(Procs0, ProcId, Proc0),
Proc0 = procedure(DeclaredDet, _, _, _, ArgModes, _, Context, CallInfo,
InferredDet),
Proc = procedure(DeclaredDet, VarSet, VarTypes, HeadVars, ArgModes,
Goal, Context, CallInfo, InferredDet),
map__set(Procs0, ProcId, Proc, Procs1),
copy_clauses_to_procs_2(ProcIds, ClausesInfo, Procs1, Procs).
:- pred select_matching_clauses(list(clause), proc_id, list(clause)).
:- mode select_matching_clauses(input, input, output).
select_matching_clauses([], _, []).
select_matching_clauses([Clause | Clauses], ProcId, MatchingClauses) :-
Clause = clause(ProcIds, _, _),
( member(ProcId, ProcIds) ->
MatchingClauses = [Clause | MatchingClauses1]
;
MatchingClauses = MatchingClauses1
),
select_matching_clauses(Clauses, ProcId, MatchingClauses1).
:- pred get_clause_goals(list(clause)::in, list(hlds__goal)::out) is det.
get_clause_goals([], []).
get_clause_goals([Clause | Clauses], [Goal | Goals]) :-
Clause = clause(_, Goal, _),
get_clause_goals(Clauses, Goals).
/*********************** ALL THIS IS COMMENTED OUT!
% Iterate over the list of clauses for a predicate.
%
:- pred modecheck_clause_list(list(clause), pred_id, tvarset, list(mode),
module_info, bool, list(clause), bool, io__state, io__state).
:- mode modecheck_clause_list(input, input, input, input, input, input,
output, output, di, uo).
modecheck_clause_list([], _PredId, _ModeVarSet, _ArgModes, _ModuleInfo, Error,
[], Error)
--> [].
modecheck_clause_list([Clause0|Clauses0], PredId, ModeVarSet, ArgModes,
ModuleInfo, Error0, [Clause|Clauses], Error) -->
modecheck_clause(Clause0, PredId, ModeVarSet, ArgModes,
ModuleInfo, Error0, Clause, Error1),
modecheck_clause_list(Clauses0, PredId, ModeVarSet, ArgModes,
ModuleInfo, Error1, Clauses, Error).
%-----------------------------------------------------------------------------%
% Mode-check a single clause.
% As we go through a clause, we determine the possible
% mode assignments for the clause. A mode assignment
% is an assignment of a mode to each variable in the
% clause.
%
% Note that this may cause exponential time & space usage
% in the presence of overloading of predicates and/or
% functors. This is a potentially serious problem, but
% there's no easy solution apparent.
%
% It would be more natural to use non-determinism to write
% this code, and perhaps even more efficient.
% But doing it deterministically would make bootstrapping more
% difficult, and most importantly would make good error
% messages very difficult.
% XXX we should do manual garbage collection here
:- pred modecheck_clause(clause, pred_id, tvarset, list(mode), module_info,
bool, clause, bool, io__state, io__state).
:- mode modecheck_clause(input, input, input, input, input, input,
output, output, di, uo).
modecheck_clause(Clause0, PredId, ModeVarSet, ArgModes, ModuleInfo, Error0,
Clause, Error, IOState0, IOState) :-
% initialize the modeinfo
% XXX abstract clause/6
Clause0 = clause(Modes, VarSet, _DummyVarModes, HeadVars, Body,
Context),
modeinfo_init(IOState0, ModuleInfo, PredId, Context, ModeVarSet,
VarSet, ModeInfo0),
% modecheck the clause - first the head unification, and
% then the body
modecheck_var_has_mode_list(HeadVars, ArgModes, ModeInfo0, ModeInfo1),
modecheck_goal(Body, ModeInfo1, ModeInfo),
% finish up
modeinfo_get_mode_assign_set(ModeInfo, ModeAssignSet),
modeinfo_get_io_state(ModeInfo, IOState1),
modecheck_finish_up(ModeAssignSet, ModeInfo, Error0, VarModes, Error,
IOState1, IOState),
Clause = clause(Modes, VarSet, VarModes, HeadVars, Body, Context).
% At this stage, there are three possibilities.
% There are either zero, one, or multiple mode assignments
% for the clause. In the first case, we have already
% issued an error message. In the second case, the
% clause is mode-correct. In the third case, we have to
% issue an error message here.
:- pred modecheck_finish_up(mode_assign_set, mode_info, bool, map(var, mode),
bool, io__state, io__state).
:- mode modecheck_finish_up(input, input, input, output, output, di, uo).
modecheck_finish_up([], _ModeInfo, _Error, VarModes, yes) -->
{ map__init(VarModes) }.
modecheck_finish_up([ModeAssign], _ModeInfo, Error, VarModes, Error) -->
{ mode_assign_get_var_modes(ModeAssign, VarModes) }.
modecheck_finish_up([ModeAssign1, ModeAssign2 | _], ModeInfo, _Error,
VarModes1, yes) -->
{ mode_assign_get_var_modes(ModeAssign1, VarModes1) },
report_ambiguity_error(ModeInfo, ModeAssign1, ModeAssign2).
%-----------------------------------------------------------------------------%
:- pred modecheck_goal(hlds__goal, mode_info, mode_info).
:- mode modecheck_goal(input, modeinfo_di, modeinfo_uo).
modecheck_goal(Goal - _GoalInfo, ModeInfo0, ModeInfo) :-
(modecheck_goal_2(Goal, ModeInfo0, ModeInfo)).
:- pred modecheck_goal_2(hlds__goal_expr, mode_info, mode_info).
:- mode modecheck_goal_2(input, modeinfo_di, modeinfo_uo).
modecheck_goal_2(conj(List)) -->
%%% checkpoint("conj"),
modecheck_goal_list(List).
modecheck_goal_2(disj(List)) -->
%%% checkpoint("disj"),
modecheck_goal_list(List).
modecheck_goal_2(if_then_else(_Vs, A, B, C)) -->
%%% checkpoint("if"),
modecheck_goal(A),
%%% checkpoint("then"),
modecheck_goal(B),
%%% checkpoint("else"),
modecheck_goal(C).
modecheck_goal_2(not(_Vs, A)) -->
%%% checkpoint("not"),
modecheck_goal(A).
modecheck_goal_2(some(_Vs, G)) -->
%%% checkpoint("some"),
modecheck_goal(G).
modecheck_goal_2(all(_Vs, G)) -->
%%% checkpoint("all"),
modecheck_goal(G).
modecheck_goal_2(call(PredId, _Mode, Args, _Builtin)) -->
%%% checkpoint("call"),
modecheck_call_pred(PredId, Args).
modecheck_goal_2(unify(A, B, _Mode, _Info)) -->
%%% checkpoint("unify"),
modecheck_unification(A, B).
%-----------------------------------------------------------------------------%
:- pred modecheck_goal_list(list(hlds__goal), mode_info, mode_info).
:- mode modecheck_goal_list(input, modeinfo_di, modeinfo_uo).
modecheck_goal_list([]) --> [].
modecheck_goal_list([Goal | Goals]) -->
modecheck_goal(Goal),
modecheck_goal_list(Goals).
%-----------------------------------------------------------------------------%
:- pred modecheck_call_pred(pred_id, list(term), mode_info, mode_info).
:- mode modecheck_call_pred(input, input, modeinfo_di, modeinfo_uo).
% XXX we should handle overloading of predicates
modecheck_call_pred(PredId, Args, ModeInfo0, ModeInfo) :-
% look up the called predicate's arg modes
modeinfo_get_preds(ModeInfo0, Preds),
( % if some [PredInfo]
map__search(Preds, PredId, PredInfo)
->
predinfo_arg_modes(PredInfo, PredModeVarSet, PredArgModes0),
% rename apart the mode variables in called
% predicate's arg modes
% (optimize for the common case of
% a non-polymorphic predicate)
( varset__is_empty(PredModeVarSet) ->
PredArgModes = PredArgModes0,
ModeInfo1 = ModeInfo0
;
rename_apart(ModeInfo0, PredModeVarSet, PredArgModes0,
ModeInfo1, PredArgModes)
),
% unify the modes of the call arguments with the
% called predicates' arg modes
modecheck_term_has_mode_list(Args, PredArgModes, ModeInfo1,
ModeInfo)
;
modeinfo_get_io_state(ModeInfo0, IOState0),
modeinfo_get_predid(ModeInfo0, CallingPredId),
modeinfo_get_context(ModeInfo0, Context),
report_error_undef_pred(CallingPredId, Context, PredId,
IOState0, IOState),
modeinfo_set_io_state(ModeInfo0, IOState, ModeInfoB1),
modeinfo_set_found_error(ModeInfoB1, yes, ModeInfoB2),
modeinfo_set_mode_assign_set(ModeInfoB2, [], ModeInfo)
).
%-----------------------------------------------------------------------------%
% Rename apart the mode variables in called predicate's arg modes.
%
% Each mode_assign has it's own set of mode variables, but these
% are supposed to stay in synch with each other. We need to
% iterate over the set of mode_assigns, but we check that
% the resulting renamed apart list of predicate arg modes
% is the same for each mode_assign (i.e. that the tvarsets
% were indeed in synch).
:- pred rename_apart(mode_info, tvarset, list(mode), mode_info, list(mode)).
:- mode rename_apart(modeinfo_di, input, input, modeinfo_uo, output).
rename_apart(ModeInfo0, PredModeVarSet, PredArgModes0, ModeInfo, PredArgModes)
:-
modeinfo_get_mode_assign_set(ModeInfo0, ModeAssignSet0),
( ModeAssignSet0 = [ModeAssign0 | ModeAssigns0] ->
% process the first mode_assign and get
% the resulting PredArgModes
mode_assign_rename_apart(ModeAssign0, PredModeVarSet,
PredArgModes0, ModeAssign, PredArgModes),
% process the remaining mode_assigns and check
% that they produce matching PredArgModes
rename_apart_2(ModeAssigns0, PredModeVarSet, PredArgModes0,
ModeAssigns, PredArgModes),
ModeAssignSet = [ModeAssign | ModeAssigns],
modeinfo_set_mode_assign_set(ModeInfo0, ModeAssignSet, ModeInfo)
;
ModeInfo = ModeInfo0
).
:- pred rename_apart_2(mode_assign_set, tvarset, list(mode),
mode_assign_set, list(mode)).
:- mode rename_apart_2(input, input, input, output, input).
rename_apart_2([], _, _, [], _).
rename_apart_2([ModeAssign0 | ModeAssigns0], PredModeVarSet, PredArgModes0,
[ModeAssign | ModeAssigns], PredArgModes) :-
mode_assign_rename_apart(ModeAssign0, PredModeVarSet, PredArgModes0,
ModeAssign, NewPredArgModes),
(PredArgModes = NewPredArgModes ->
true
;
error("problem synchronizing mode vars")
),
rename_apart_2(ModeAssigns0, PredModeVarSet, PredArgModes0,
ModeAssigns, PredArgModes).
:- pred mode_assign_rename_apart(mode_assign, tvarset, list(mode),
mode_assign, list(mode)).
:- mode mode_assign_rename_apart(input, input, input, output, output).
mode_assign_rename_apart(ModeAssign0, PredModeVarSet, PredArgModes0,
ModeAssign, PredArgModes) :-
mode_assign_get_modevarset(ModeAssign0, ModeVarSet0),
varset__merge(ModeVarSet0, PredModeVarSet, PredArgModes0,
ModeVarSet, PredArgModes),
mode_assign_set_modevarset(ModeAssign0, ModeVarSet, ModeAssign).
%-----------------------------------------------------------------------------%
% Given a list of variables and a list of modes, ensure
% that each variable has the corresponding mode.
:- pred modecheck_var_has_mode_list(list(var), list(mode), mode_info,
mode_info).
:- mode modecheck_var_has_mode_list(input, input, input, output).
modecheck_var_has_mode_list([], []) --> [].
modecheck_var_has_mode_list([Var|Vars], [Mode|Modes]) -->
modecheck_var_has_mode(Var, Mode),
modecheck_var_has_mode_list(Vars, Modes).
:- pred modecheck_var_has_mode(var, mode, mode_info, mode_info).
:- mode modecheck_var_has_mode(input, input, modeinfo_di, modeinfo_uo).
modecheck_var_has_mode(VarId, Mode, ModeInfo0, ModeInfo) :-
modeinfo_get_mode_assign_set(ModeInfo0, ModeAssignSet0),
modeinfo_get_varset(ModeInfo0, VarSet),
modecheck_var_has_mode_2(ModeAssignSet0, VarId, Mode, [],
ModeAssignSet),
(
ModeAssignSet = [],
(not ModeAssignSet0 = [])
->
modeinfo_get_io_state(ModeInfo0, IOState0),
modeinfo_get_context(ModeInfo0, Context),
modeinfo_get_predid(ModeInfo0, PredId),
get_mode_stuff(ModeAssignSet0, VarId, ModeStuffList),
report_error_var(PredId, Context, VarSet, VarId, ModeStuffList,
Mode, ModeAssignSet0, IOState0, IOState),
modeinfo_set_io_state(ModeInfo0, IOState, ModeInfo1),
modeinfo_set_found_error(ModeInfo1, yes, ModeInfo2),
modeinfo_set_mode_assign_set(ModeInfo2, ModeAssignSet, ModeInfo)
;
modeinfo_set_mode_assign_set(ModeInfo0, ModeAssignSet, ModeInfo)
).
% Given a mode assignment set and a variable id,
% return the list of possible different modes for the variable.
:- mode mode_stuff ---> mode_stuff(mode, tvarset, tsubst).
:- pred get_mode_stuff(mode_assign_set, var, list(mode_stuff)).
:- mode get_mode_stuff(input, input, output).
get_mode_stuff([], _VarId, []).
get_mode_stuff([ModeAssign | ModeAssigns], VarId, L) :-
get_mode_stuff(ModeAssigns, VarId, L0),
mode_assign_get_mode_bindings(ModeAssign, ModeBindings),
mode_assign_get_modevarset(ModeAssign, TVarSet),
mode_assign_get_var_modes(ModeAssign, VarModes),
( %%% if some [Mode0]
map__search(VarModes, VarId, Mode0)
->
Mode = Mode0
;
% this shouldn't happen - how can a variable which has
% not yet been assigned a mode variable fail to have
% the correct mode?
error("problem in mode unification")
),
ModeStuff = mode_stuff(Mode, TVarSet, ModeBindings),
(
member_chk(ModeStuff, L0)
->
L = L0
;
L = [ModeStuff | L0]
).
:- pred modecheck_var_has_mode_2(mode_assign_set, var, mode,
mode_assign_set, mode_assign_set).
:- mode modecheck_var_has_mode_2(input, input, input, input, output).
modecheck_var_has_mode_2([], _, _) --> [].
modecheck_var_has_mode_2([ModeAssign0 | ModeAssignSet0], VarId, Mode) -->
mode_assign_var_has_mode(ModeAssign0, VarId, Mode),
modecheck_var_has_mode_2(ModeAssignSet0, VarId, Mode).
:- pred mode_assign_var_has_mode(mode_assign, var, mode,
mode_assign_set, mode_assign_set).
:- mode mode_assign_var_has_mode(input, input, input, input, output).
mode_assign_var_has_mode(ModeAssign0, VarId, Mode,
ModeAssignSet0, ModeAssignSet) :-
mode_assign_get_var_modes(ModeAssign0, VarModes0),
( %%% if some [VarMode]
map__search(VarModes0, VarId, VarMode)
->
( %%% if some [ModeAssign1]
mode_assign_unify_mode(ModeAssign0, VarMode, Mode,
ModeAssign1)
->
ModeAssignSet = [ModeAssign1 | ModeAssignSet0]
;
ModeAssignSet = ModeAssignSet0
)
;
map__set(VarModes0, VarId, Mode, VarModes),
mode_assign_set_var_modes(ModeAssign0, VarModes, ModeAssign),
ModeAssignSet = [ModeAssign | ModeAssignSet0]
).
%-----------------------------------------------------------------------------%
:- pred modecheck_term_has_mode_list(list(term), list(mode),
mode_info, mode_info).
:- mode modecheck_term_has_mode_list(input, input, modeinfo_di, modeinfo_uo).
modecheck_term_has_mode_list([], []) --> [].
modecheck_term_has_mode_list([Arg | Args], [Mode | Modes]) -->
modecheck_term_has_mode(Arg, Mode),
modecheck_term_has_mode_list(Args, Modes).
:- pred modecheck_term_has_mode(term, mode, mode_info, mode_info).
:- mode modecheck_term_has_mode(input, input, modeinfo_di, modeinfo_uo).
modecheck_term_has_mode(term_variable(Var), Mode, ModeInfo0, ModeInfo) :-
modecheck_var_has_mode(Var, Mode, ModeInfo0, ModeInfo).
modecheck_term_has_mode(term_functor(F, As, C), Mode, ModeInfo0, ModeInfo) :-
length(As, Arity),
modeinfo_get_ctor_list(ModeInfo0, F, Arity, ConsDefnList),
(ConsDefnList = [] ->
modeinfo_get_io_state(ModeInfo0, IOState0),
modeinfo_get_predid(ModeInfo0, PredId),
report_error_undef_cons(PredId, C, F, Arity, IOState0, IOState),
modeinfo_set_io_state(ModeInfo0, IOState, ModeInfo1),
modeinfo_set_found_error(ModeInfo1, yes, ModeInfo2),
modeinfo_set_mode_assign_set(ModeInfo2, [], ModeInfo)
;
modeinfo_get_mode_assign_set(ModeInfo0, ModeAssignSet0),
modecheck_cons_has_mode(ModeAssignSet0, ConsDefnList, As, Mode,
ModeInfo0, [], ModeAssignSet),
(
ModeAssignSet = [],
(\+ ModeAssignSet0 = [])
->
modeinfo_get_io_state(ModeInfo0, IOState0),
modeinfo_get_predid(ModeInfo0, PredId),
modeinfo_get_varset(ModeInfo0, VarSet),
report_error_cons(PredId, C, VarSet, F, As, Mode,
ModeAssignSet, IOState0, IOState),
modeinfo_set_io_state(ModeInfo0, IOState, ModeInfo1),
modeinfo_set_found_error(ModeInfo1, yes, ModeInfo2),
modeinfo_set_mode_assign_set(ModeInfo2, ModeAssignSet, ModeInfo)
;
modeinfo_set_mode_assign_set(ModeInfo0, ModeAssignSet, ModeInfo)
)
).
%-----------------------------------------------------------------------------%
% Check that a constructor has the specified mode
% and that the arguments of the constructor have the appropriate
% modes for that constructor.
% We do this by iterating over all the possible current
% mode assignments.
% For each possible current mode assignment, we produce a
% list of the possible resulting mode assignments after
% we have unified the mode of this constructor with
% the specified mode.
:- pred modecheck_cons_has_mode(mode_assign_set, list(hlds__cons_defn),
list(term), mode, mode_info, mode_assign_set, mode_assign_set).
:- mode modecheck_cons_has_mode(input, input, input, input,
modeinfo_ui, input, output).
modecheck_cons_has_mode([], _, _, _, _) --> [].
modecheck_cons_has_mode([ModeAssign|ModeAssigns], ConsDefnList, Args, Mode,
ModeInfo) -->
mode_assign_cons_has_mode(ConsDefnList, ModeAssign, Args, Mode,
ModeInfo),
modecheck_cons_has_mode(ModeAssigns, ConsDefnList, Args, Mode,
ModeInfo).
%-----------------------------------------------------------------------------%
% For each possible constructor which matches the
% term (overloading means that there may be more than one),
% if this constructor matches the specified mode and
% the modes of it's arguments are ok, then add the resulting
% mode assignment to the mode assignment set.
:- pred mode_assign_cons_has_mode(list(hlds__cons_defn), mode_assign,
list(term), mode, mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_cons_has_mode(input, input, input, input,
modeinfo_ui, input, output).
mode_assign_cons_has_mode([], _ModeAssign0, _Args, _Mode, _ModeInfo) -->
[].
mode_assign_cons_has_mode([ConsDefn | ConsDefns], ModeAssign0, Args, Mode,
ModeInfo) -->
mode_assign_cons_has_mode_2(ConsDefn, ModeAssign0, Args, Mode,
ModeInfo),
mode_assign_cons_has_mode(ConsDefns, ModeAssign0, Args, Mode, ModeInfo).
:- pred mode_assign_cons_has_mode_2(hlds__cons_defn, mode_assign, list(term),
mode, mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_cons_has_mode_2(input, input, input, input,
modeinfo_ui, input, output).
mode_assign_cons_has_mode_2(ConsDefn, ModeAssign0, Args, Mode, ModeInfo,
ModeAssignSet0, ModeAssignSet) :-
get_cons_stuff(ConsDefn, ModeAssign0, ModeInfo,
ConsMode, ArgModes, ModeAssign1),
( mode_assign_unify_mode(ModeAssign1, ConsMode, Mode, ModeAssign2) ->
% check the modes of the arguments
mode_assign_term_has_mode_list(Args, ArgModes, ModeAssign2,
ModeInfo, ModeAssignSet0, ModeAssignSet)
;
ModeAssignSet = ModeAssignSet0
).
%-----------------------------------------------------------------------------%
% mode_assign_term_has_mode_list(Terms, Modes, ModeAssign, ModeInfo,
% ModeAssignSet0, ModeAssignSet):
% Let TAs = { TA | TA is a an extension of ModeAssign
% for which the modes of the Terms unify with
% their respective Modes },
% append(TAs, ModeAssignSet0, ModeAssignSet).
:- pred mode_assign_term_has_mode_list(list(term), list(mode), mode_assign,
mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_term_has_mode_list(input, input, input,
modeinfo_ui, input, output).
mode_assign_term_has_mode_list([], [], ModeAssign, _,
ModeAssignSet, [ModeAssign|ModeAssignSet]).
mode_assign_term_has_mode_list([Arg | Args], [Mode | Modes], ModeAssign0,
ModeInfo, ModeAssignSet0, ModeAssignSet) :-
mode_assign_term_has_mode(Arg, Mode, ModeAssign0, ModeInfo,
[], ModeAssignSet1),
mode_assign_list_term_has_mode_list(ModeAssignSet1,
Args, Modes, ModeInfo, ModeAssignSet0, ModeAssignSet).
% mode_assign_list_term_has_mode_list(TAs, Terms, Modes,
% ModeInfo, ModeAssignSet0, ModeAssignSet):
% Let TAs2 = { TA | TA is a an extension of a member of TAs
% for which the modes of the Terms unify with
% their respective Modes },
% append(TAs, ModeAssignSet0, ModeAssignSet).
:- pred mode_assign_list_term_has_mode_list(mode_assign_set, list(term),
list(mode), mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_list_term_has_mode_list(input, input, input,
modeinfo_ui, input, output).
mode_assign_list_term_has_mode_list([], _, _, _) --> [].
mode_assign_list_term_has_mode_list([TA | TAs], Args, Modes, ModeInfo) -->
mode_assign_term_has_mode_list(Args, Modes, TA, ModeInfo),
mode_assign_list_term_has_mode_list(TAs, Args, Modes, ModeInfo).
:- pred mode_assign_term_has_mode(term, mode, mode_assign,
mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_term_has_mode(input, input, input,
modeinfo_ui, input, output).
mode_assign_term_has_mode(term_variable(V), Mode, ModeAssign, _ModeInfo) -->
mode_assign_var_has_mode(ModeAssign, V, Mode).
mode_assign_term_has_mode(term_functor(F, Args, _Context), Mode, ModeAssign,
ModeInfo) -->
{ length(Args, Arity) },
{ modeinfo_get_ctor_list(ModeInfo, F, Arity, ConsDefnList) },
mode_assign_cons_has_mode(ConsDefnList, ModeAssign, Args, Mode,
ModeInfo).
%-----------------------------------------------------------------------------%
% used for debugging
:- pred checkpoint(string, mode_info, mode_info).
:- mode checkpoint(input, modeinfo_di, modeinfo_uo).
%%% checkpoint(_, T, T).
checkpoint(Msg, T0, T) :-
modeinfo_get_io_state(T0, I0),
checkpoint_2(Msg, T0, I0, I),
modeinfo_set_io_state(T0, I, T).
:- pred checkpoint_2(string, mode_info, io__state, io__state).
:- mode checkpoint_2(input, modeinfo_ui, di, uo).
checkpoint_2(Msg, T0) -->
io__write_string("At "),
io__write_string(Msg),
io__write_string(": "),
%%% { report_stats },
io__write_string("\n"),
{ modeinfo_get_mode_assign_set(T0, ModeAssignSet) },
{ modeinfo_get_varset(T0, VarSet) },
write_mode_assign_set(ModeAssignSet, VarSet).
%-----------------------------------------------------------------------------%
% Mode check a unification.
% Get the mode assignment set from the mode info and then just
% iterate over all the possible mode assignments.
:- pred modecheck_unification(term, term, mode_info, mode_info).
:- mode modecheck_unification(input, input, modeinfo_di, modeinfo_uo).
modecheck_unification(X, Y, ModeInfo0, ModeInfo) :-
modeinfo_get_mode_assign_set(ModeInfo0, ModeAssignSet0),
modecheck_unification_2(ModeAssignSet0, X, Y, ModeInfo0,
[], ModeAssignSet),
% XXX report errors properly!!
( ModeAssignSet = [], not (ModeAssignSet0 = []) ->
modeinfo_get_predid(ModeInfo0, PredId),
modeinfo_get_context(ModeInfo0, Context),
modeinfo_get_varset(ModeInfo0, VarSet),
modeinfo_get_io_state(ModeInfo0, IOState0),
report_error_unif(PredId, Context, VarSet, X, Y,
ModeAssignSet0, IOState0, IOState1),
modeinfo_set_io_state(ModeInfo0, IOState1, ModeInfo1),
modeinfo_set_found_error(ModeInfo1, yes, ModeInfo2)
;
ModeInfo2 = ModeInfo0
),
modeinfo_set_mode_assign_set(ModeInfo2, ModeAssignSet, ModeInfo).
% iterate over all the possible mode assignments.
:- pred modecheck_unification_2(mode_assign_set, term, term,
mode_info, mode_assign_set, mode_assign_set).
:- mode modecheck_unification_2(input, input, input,
modeinfo_ui, input, output).
modecheck_unification_2([], _, _, _) --> [].
modecheck_unification_2([ModeAssign0 | ModeAssigns0], X, Y, ModeInfo) -->
mode_assign_unify_term(X, Y, ModeAssign0, ModeInfo),
modecheck_unification_2(ModeAssigns0, X, Y, ModeInfo).
%-----------------------------------------------------------------------------%
% Mode-check the unification of two terms,
% and update the mode assignment.
% ModeAssign0 is the mode assignment we are updating,
% ModeAssignSet0 is an accumulator for the list of possible
% mode assignments so far, and ModeAssignSet is ModeAssignSet plus
% any mode assignment(s) resulting from ModeAssign0 and this
% unification.
:- pred mode_assign_unify_term(term, term, mode_assign, mode_info,
mode_assign_set, mode_assign_set).
:- mode mode_assign_unify_term(input, input, input, modeinfo_ui, input, output).
% NU-Prolog indexing
:- mode_assign_unify_term(T1, T2, _, _, _, _) when T1 and T2.
mode_assign_unify_term(term_variable(X), term_variable(Y), ModeAssign0,
_ModeInfo, ModeAssignSet0, ModeAssignSet) :-
mode_assign_get_var_modes(ModeAssign0, VarModes0),
( %%% if some [ModeX]
map__search(VarModes0, X, ModeX)
->
( %%% if some [ModeY]
map__search(VarModes0, Y, ModeY)
->
% both X and Y already have modes - just
% unify their modes
( %%% if some [ModeAssign3]
mode_assign_unify_mode(ModeAssign0, ModeX,
ModeY, ModeAssign3)
->
ModeAssignSet = [ModeAssign3 | ModeAssignSet0]
;
ModeAssignSet = ModeAssignSet0
)
;
% Y is a fresh variable which hasn't been
% assigned a mode yet
map__set(VarModes0, Y, ModeX, VarModes),
mode_assign_set_var_modes(ModeAssign0, VarModes,
ModeAssign),
ModeAssignSet = [ModeAssign | ModeAssignSet0]
)
;
( %%% if some [ModeY2]
map__search(VarModes0, Y, ModeY2)
->
% X is a fresh variable which hasn't been
% assigned a mode yet
map__set(VarModes0, X, ModeY2, VarModes),
mode_assign_set_var_modes(ModeAssign0, VarModes,
ModeAssign),
ModeAssignSet = [ModeAssign | ModeAssignSet0]
;
% both X and Y are fresh variables -
% introduce a fresh mode variable to represent
% their mode
mode_assign_get_modevarset(ModeAssign0, ModeVarSet0),
varset__new_var(ModeVarSet0, ModeVar, ModeVarSet),
mode_assign_set_modevarset(ModeAssign0, ModeVarSet,
ModeAssign1),
Mode = term_variable(ModeVar),
map__set(VarModes0, X, Mode, VarModes1),
map__set(VarModes1, Y, Mode, VarModes),
mode_assign_set_var_modes(ModeAssign1, VarModes,
ModeAssign),
ModeAssignSet = [ModeAssign | ModeAssignSet0]
)
).
mode_assign_unify_term(term_functor(Functor, Args, _), term_variable(Y),
ModeAssign0, ModeInfo, ModeAssignSet0, ModeAssignSet) :-
length(Args, Arity),
modeinfo_get_ctor_list(ModeInfo, Functor, Arity, ConsDefnList),
mode_assign_unify_var_functor(ConsDefnList, Args, Y, ModeAssign0,
ModeInfo, ModeAssignSet0, ModeAssignSet).
mode_assign_unify_term(term_variable(Y), term_functor(F, As, _), ModeAssign0,
ModeInfo, ModeAssignSet0, ModeAssignSet) :-
mode_assign_unify_term(term_functor(F, As, _), term_variable(Y),
ModeAssign0, ModeInfo, ModeAssignSet0, ModeAssignSet).
mode_assign_unify_term(term_functor(FX, AsX, _), term_functor(FY, AsY, _),
ModeAssign0, ModeInfo, ModeAssignSet0, ModeAssignSet) :-
% XXX we should handle this properly
error("XXX not implemented: unification of term with term\n"),
ModeAssignSet = ModeAssignSet0.
%-----------------------------------------------------------------------------%
% Mode-check the unification of a variable with a functor:
% for each possible mode of the constructor,
% unify the mode of the variable with the mode of
% the constructor and if this succeeds insert that
% mode assignment into the mode assignment set.
:- pred mode_assign_unify_var_functor(list(hlds__cons_defn), list(term),
var, mode_assign,
mode_info, mode_assign_set, mode_assign_set).
:- mode mode_assign_unify_var_functor(input, input, input, input,
modeinfo_ui, input, output).
mode_assign_unify_var_functor([], _, _, _, _, ModeAssignSet, ModeAssignSet).
mode_assign_unify_var_functor([ConsDefn | ConsDefns], Args, Y, ModeAssign0,
ModeInfo, ModeAssignSet0, ModeAssignSet) :-
get_cons_stuff(ConsDefn, ModeAssign0, ModeInfo,
ConsMode, ArgModes, ModeAssign1),
% unify the mode of Var with the mode of the constructor
mode_assign_get_var_modes(ModeAssign1, VarModes0),
( %%% if some [ModeY]
map__search(VarModes0, Y, ModeY)
->
( %%% if some [ModeAssign2]
mode_assign_unify_mode(ModeAssign1, ConsMode, ModeY,
ModeAssign2)
->
% check that the modes of the arguments matches the
% specified arg modes for this constructor
mode_assign_term_has_mode_list(Args, ArgModes,
ModeAssign2, ModeInfo,
ModeAssignSet0, ModeAssignSet1)
;
% the top-level modes didn't unify - no need to
% check the modes of the arguments, since this
% mode-assignment has already been rules out
ModeAssignSet1 = ModeAssignSet0
)
;
map__set(VarModes0, Y, ConsMode, VarModes),
mode_assign_set_var_modes(ModeAssign1, VarModes, ModeAssign3),
% check that the modes of the arguments matches the
% specified arg modes for this constructor
mode_assign_term_has_mode_list(Args, ArgModes, ModeAssign3,
ModeInfo, ModeAssignSet0, ModeAssignSet1)
),
% recursively handle all the other possible constructors
% that match this functor.
mode_assign_unify_var_functor(ConsDefns, Args, Y, ModeAssign0,
ModeInfo, ModeAssignSet1, ModeAssignSet).
%-----------------------------------------------------------------------------%
% Given an hlds__cons_defn, construct a mode for the
% constructor and a list of modes of the arguments.
% First we construct the mode and the arg modes using
% the information in the hlds__cons_defn and the information
% in the hlds mode table entry for the cons' mode.
% Then we rename these apart from the current mode_assign's
% modevarset.
%
% XXX abstract the use of hlds__cons_defn/3 and hlds__mode_defn/5
:- pred get_cons_stuff(hlds__cons_defn, mode_assign, mode_info,
mode, list(mode), mode_assign).
:- mode get_cons_stuff(input, input, input, output, output, output).
get_cons_stuff(ConsDefn, ModeAssign0, ModeInfo, ConsMode, ArgModes,
ModeAssign) :-
ConsDefn = hlds__cons_defn(ArgModes0, ModeId, Context),
( is_builtin_mode(ModeId) ->
% XXX assumes arity = 0
varset__init(ConsModeVarSet),
ConsModeParams = []
;
modeinfo_get_modes(ModeInfo, Modes),
map__search(Modes, ModeId, ModeDefn),
ModeDefn = hlds__mode_defn(ConsModeVarSet, ConsModeParams,
_, _, _)
),
ModeId = QualifiedName - _Arity,
unqualify_name(QualifiedName, Name),
ConsMode0 = term_functor(term_atom(Name), ConsModeParams, Context),
% Rename apart the mode vars in the mode of the constructor
% and the modes of it's arguments.
% (Optimize the common case of a non-polymorphic mode)
(ConsModeParams = [] ->
ConsMode = ConsMode0,
ArgModes = ArgModes0,
ModeAssign = ModeAssign0
;
mode_assign_rename_apart(ModeAssign0, ConsModeVarSet,
[ConsMode0 | ArgModes0],
ModeAssign, [ConsMode | ArgModes])
).
%-----------------------------------------------------------------------------%
% Unify (with occurs check) two modes in a mode assignment
% and update the mode bindings.
:- pred mode_assign_unify_mode(mode_assign, mode, mode, mode_assign).
:- mode mode_assign_unify_mode(input, input, input, output).
mode_assign_unify_mode(ModeAssign0, X, Y, ModeAssign) :-
mode_assign_get_mode_bindings(ModeAssign0, ModeBindings0),
mode_unify(X, Y, ModeBindings0, ModeBindings),
mode_assign_set_mode_bindings(ModeAssign0, ModeBindings, ModeAssign).
%-----------------------------------------------------------------------------%
% Unify (with occurs check) two modes with respect to a mode
% substitution and update the mode bindings.
% (Modes are represented as terms, but we can't just use term__unify
% because we need to handle equivalent modes).
:- mode_unify(X, Y, _, _) when X and Y. % NU-Prolog indexing
:- pred mode_unify(mode, mode, substitution, substitution).
:- mode mode_unify(input, input, input, output).
mode_unify(term_variable(X), term_variable(Y), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
( %%% if some [BindingOfY]
map__search(Bindings0, Y, BindingOfY)
->
% both X and Y already have bindings - just
% unify the modes they are bound to
mode_unify(BindingOfX, BindingOfY, Bindings0, Bindings)
;
term__apply_rec_substitution(BindingOfX,
Bindings0, SubstBindingOfX),
% Y is a mode variable which hasn't been bound yet
( SubstBindingOfX = term_variable(Y) ->
Bindings = Bindings0
;
\+ term__occurs(SubstBindingOfX, Y, Bindings0),
map__set(Bindings0, Y, SubstBindingOfX,
Bindings)
)
)
;
( %%% if some [BindingOfY2]
map__search(Bindings0, Y, BindingOfY2)
->
term__apply_rec_substitution(BindingOfY2,
Bindings0, SubstBindingOfY2),
% X is a mode variable which hasn't been bound yet
( SubstBindingOfY2 = term_variable(X) ->
Bindings = Bindings0
;
\+ term__occurs(SubstBindingOfY2, X, Bindings0),
map__set(Bindings0, X, SubstBindingOfY2,
Bindings)
)
;
% both X and Y are unbound mode variables -
% bind one to the other
( X = Y ->
Bindings = Bindings0
;
map__set(Bindings0, X, term_variable(Y),
Bindings)
)
)
).
mode_unify(term_variable(X), term_functor(F, As, C), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
mode_unify(BindingOfX, term_functor(F, As, C), Bindings0,
Bindings)
;
\+ term__occurs_list(As, X, Bindings0),
map__set(Bindings0, X, term_functor(F, As, C), Bindings)
).
mode_unify(term_functor(F, As, C), term_variable(X), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
\+ term__occurs_list(As, X, Bindings0),
mode_unify(term_functor(F, As, C), BindingOfX, Bindings0,
Bindings)
;
map__set(Bindings0, X, term_functor(F, As, C), Bindings)
).
mode_unify(term_functor(FX, AsX, _), term_functor(FY, AsY, _), Bindings0,
Bindings) :-
length(AsX, ArityX),
length(AsY, ArityY),
(
FX = FY,
ArityX = ArityY
->
mode_unify_list(AsX, AsY, Bindings0, Bindings)
;
% XXX check if these modes have been defined to be
% equivalent using equivalence modes
fail % XXX stub only!!!
).
:- pred mode_unify_list(list(mode), list(mode), substitution, substitution).
:- mode mode_unify_list(input, input, input, output).
mode_unify_list([], []) --> [].
mode_unify_list([X | Xs], [Y | Ys]) -->
mode_unify(X, Y),
mode_unify_list(Xs, Ys).
ALL THIS IS COMMENTED OUT! ***********************/
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% XXX - At the moment we don't check for circular modes.
% (If they aren't used, the compiler will probably not
% detect the error; if they are, it will probably go into
% an infinite loop).
:- pred check_circular_modes(module_info, module_info, io__state, io__state).
:- mode check_circular_modes(input, output, di, uo).
check_circular_modes(Module0, Module) -->
{ Module = Module0 }.
/**** JUNK
{ moduleinfo_modes(Module0, Modes0 },
{ map__keys(Modes0, ModeIds) },
check_circular_modes_2(ModeIds, Modes0, Modes),
{ moduleinfo_set_modes(Module0, Modes, Module) }.
check_circular_modes_2([], Modes, Modes) --> [].
check_circular_modes_2([ModeId | ModeIds], Modes0, Modes) -->
JUNK ****/
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% Check for any possible undefined insts/modes.
% XXX should we add a definition for undefined modes?
:- pred check_undefined_modes(module_info, module_info, io__state, io__state).
:- mode check_undefined_modes(input, output, di, uo).
check_undefined_modes(Module, Module) -->
{ moduleinfo_insts(Module, InstDefns) },
{ map__keys(InstDefns, InstIds) },
find_undef_inst_bodies(InstIds, InstDefns),
{ moduleinfo_modes(Module, ModeDefns) },
{ map__keys(ModeDefns, ModeIds) },
find_undef_mode_bodies(ModeIds, ModeDefns, InstDefns),
{ moduleinfo_preds(Module, Preds) },
{ moduleinfo_predids(Module, PredIds) },
find_undef_pred_modes(PredIds, Preds, ModeDefns, InstDefns).
% Find any undefined insts/modes used in predicate mode declarations.
:- pred find_undef_pred_modes(list(pred_id), pred_table, mode_table,
inst_table, io__state, io__state).
:- mode find_undef_pred_modes(input, input, input, input, di, uo).
find_undef_pred_modes([], _Preds, _ModeDefns, _InstDefns) --> [].
find_undef_pred_modes([PredId | PredIds], Preds, ModeDefns, InstDefns) -->
{ map__search(Preds, PredId, PredDefn) },
{ predinfo_procedures(PredDefn, Procs) },
{ map__keys(Procs, ProcIds) },
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns),
find_undef_pred_modes(PredIds, Preds, ModeDefns, InstDefns).
:- pred find_undef_proc_modes(list(proc_id), pred_id, proc_table, mode_table,
inst_table, io__state, io__state).
:- mode find_undef_proc_modes(input, input, input, input, input, di, uo).
find_undef_proc_modes([], _PredId, _Procs, _ModeDefns, _InstDefns) --> [].
find_undef_proc_modes([ProcId | ProcIds], PredId, Procs, ModeDefns,
InstDefns) -->
{ map__search(Procs, ProcId, ProcDefn) },
{ procinfo_argmodes(ProcDefn, ArgModes) },
{ procinfo_context(ProcDefn, Context) },
find_undef_mode_list(ArgModes, pred(PredId) - Context, ModeDefns,
InstDefns),
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns).
%-----------------------------------------------------------------------------%
% Find any undefined insts/modes used in the bodies of other mode
% declarations.
:- pred find_undef_mode_bodies(list(mode_id), mode_table, inst_table,
io__state, io__state).
:- mode find_undef_mode_bodies(input, input, input, di, uo).
find_undef_mode_bodies([], _, _) --> [].
find_undef_mode_bodies([ModeId | ModeIds], ModeDefns, InstDefns) -->
{ map__search(ModeDefns, ModeId, HLDS_ModeDefn) },
% XXX abstract hlds__mode_defn/5
{ HLDS_ModeDefn = hlds__mode_defn(_, _, Mode, _, Context) },
find_undef_mode_body(Mode, mode(ModeId) - Context, ModeDefns,
InstDefns),
find_undef_mode_bodies(ModeIds, ModeDefns, InstDefns).
% Find any undefined insts/modes used in the given mode definition.
:- pred find_undef_mode_body(hlds__mode_body, mode_error_context,
mode_table, inst_table, io__state, io__state).
:- mode find_undef_mode_body(input, input, input, input, di, uo).
find_undef_mode_body(eqv_mode(Mode), ErrorContext, ModeDefns, InstDefns) -->
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns).
% Find any undefined modes in a list of modes.
:- pred find_undef_mode_list(list(mode), mode_error_context,
mode_table, inst_table, io__state, io__state).
:- mode find_undef_mode_list(input, input, input, input, di, uo).
find_undef_mode_list([], _, _, _) --> [].
find_undef_mode_list([Mode|Modes], ErrorContext, ModeDefns, InstDefns) -->
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns),
find_undef_mode_list(Modes, ErrorContext, ModeDefns, InstDefns).
% Find any undefined modes/insts used in a mode.
% The mode itself may be undefined, and also
% any inst arguments may also be undefined.
% (eg. the mode `undef1(undef2, undef3)' should generate 3 errors.)
:- pred find_undef_mode(mode, mode_error_context, mode_table, inst_table,
io__state, io__state).
:- mode find_undef_mode(input, input, input, input, di, uo).
find_undef_mode((InstA -> InstB), ErrorContext, _ModeDefns, InstDefns) -->
find_undef_inst(InstA, ErrorContext, InstDefns),
find_undef_inst(InstB, ErrorContext, InstDefns).
find_undef_mode(user_defined_mode(Name, Args), ErrorContext, ModeDefns,
InstDefns) -->
{ length(Args, Arity) },
{ ModeId = Name - Arity },
(
{ \+ map__contains(ModeDefns, ModeId)
%%% \+ is_builtin_mode(ModeId) % no builtin modes as yet
}
->
report_undef_mode(ModeId, ErrorContext)
;
[]
),
find_undef_inst_list(Args, ErrorContext, InstDefns).
%-----------------------------------------------------------------------------%
% Find any undefined insts used in the bodies of other inst
% declarations.
:- pred find_undef_inst_bodies(list(inst_id), inst_table, io__state, io__state).
:- mode find_undef_inst_bodies(input, input, di, uo).
find_undef_inst_bodies([], _) --> [].
find_undef_inst_bodies([InstId | InstIds], InstDefns) -->
{ map__search(InstDefns, InstId, HLDS_InstDefn) },
% XXX abstract hlds__inst_defn/5
{ HLDS_InstDefn = hlds__inst_defn(_, _, Inst, _, Context) },
find_undef_inst_body(Inst, inst(InstId) - Context, InstDefns),
find_undef_inst_bodies(InstIds, InstDefns).
% Find any undefined insts used in the given inst definition.
:- pred find_undef_inst_body(hlds__inst_body, mode_error_context, inst_table,
io__state, io__state).
:- mode find_undef_inst_body(input, input, input, di, uo).
find_undef_inst_body(eqv_inst(Inst), ErrorContext, InstDefns) -->
find_undef_inst(Inst, ErrorContext, InstDefns).
find_undef_inst_body(abstract_inst, _, _) --> [].
% Find any undefined insts in a list of insts.
:- pred find_undef_inst_list(list(inst), mode_error_context, inst_table,
io__state, io__state).
:- mode find_undef_inst_list(input, input, input, di, uo).
find_undef_inst_list([], _ErrorContext, _InstDefns) --> [].
find_undef_inst_list([Inst|Insts], ErrorContext, InstDefns) -->
find_undef_inst(Inst, ErrorContext, InstDefns),
find_undef_inst_list(Insts, ErrorContext, InstDefns).
% Find any undefined insts used in an inst.
% The inst itself may be undefined, and also
% any inst arguments may also be undefined.
% (eg. the inst `undef1(undef2, undef3)' should generate 3 errors.)
:- pred find_undef_inst(inst, mode_error_context, inst_table,
io__state, io__state).
:- mode find_undef_inst(input, input, input, di, uo).
find_undef_inst(free, _, _) --> [].
find_undef_inst(ground, _, _) --> [].
find_undef_inst(inst_var(_), _, _) --> [].
find_undef_inst(bound(BoundInsts), ErrorContext, InstDefns) -->
find_undef_bound_insts(BoundInsts, ErrorContext, InstDefns).
find_undef_inst(user_defined_inst(Name, Args), ErrorContext, InstDefns) -->
{ length(Args, Arity) },
{ InstId = Name - Arity },
(
{ \+ map__contains(InstDefns, InstId) }
%%% \+ is_builtin_inst(InstId) % no builtin modes as yet
->
report_undef_inst(InstId, ErrorContext)
;
[]
),
find_undef_inst_list(Args, ErrorContext, InstDefns).
find_undef_inst(abstract_inst(Name, Args), ErrorContext, InstDefns) -->
find_undef_inst(user_defined_inst(Name, Args), ErrorContext, InstDefns).
:- pred find_undef_bound_insts(list(bound_inst), mode_error_context, inst_table,
io__state, io__state).
:- mode find_undef_bound_insts(input, input, input, di, uo).
find_undef_bound_insts([], _, _) --> [].
find_undef_bound_insts([functor(_Name, Args) | BoundInsts], ErrorContext,
InstDefns) -->
find_undef_inst_list(Args, ErrorContext, InstDefns),
find_undef_bound_insts(BoundInsts, ErrorContext, InstDefns).
%-----------------------------------------------------------------------------%
:- type mode_error_context == pair(mode_error_context_2, term__context).
:- type mode_error_context_2 ---> inst(inst_id)
; mode(mode_id)
; pred(pred_id).
% Output an error message about an undefined mode
% in the specified context.
:- pred report_undef_mode(mode_id, mode_error_context, io__state, io__state).
:- mode report_undef_mode(input, input, di, uo).
report_undef_mode(ModeId, ErrorContext - Context) -->
prog_out__write_context(Context),
io__write_string("In "),
write_mode_error_context(ErrorContext),
io__write_string(":\n"),
prog_out__write_context(Context),
io__write_string("error: undefined mode "),
write_mode_id(ModeId),
io__write_string(".\n").
% Output an error message about an undefined inst
% in the specified context.
:- pred report_undef_inst(inst_id, mode_error_context, io__state, io__state).
:- mode report_undef_inst(input, input, di, uo).
report_undef_inst(InstId, ErrorContext - Context) -->
prog_out__write_context(Context),
io__write_string("In "),
write_mode_error_context(ErrorContext),
io__write_string(":\n"),
prog_out__write_context(Context),
io__write_string("error: undefined inst "),
write_inst_id(InstId),
io__write_string(".\n").
% Output a description of the context where an undefined mode was
% used.
:- pred write_mode_error_context(mode_error_context_2, io__state, io__state).
:- mode write_mode_error_context(input, di, uo).
write_mode_error_context(pred(PredId)) -->
io__write_string("mode declaration for predicate "),
write_pred_id(PredId).
write_mode_error_context(mode(ModeId)) -->
io__write_string("definition of mode "),
write_mode_id(ModeId).
write_mode_error_context(inst(InstId)) -->
io__write_string("definition of inst "),
write_inst_id(InstId).
%-----------------------------------------------------------------------------%
% Predicates to output mode_ids and pred_ids.
% XXX mode_ids should include the module.
:- pred write_mode_id(mode_id, io__state, io__state).
:- mode write_mode_id(input, di, uo).
write_mode_id(F - N) -->
prog_out__write_sym_name(F),
io__write_string("/"),
io__write_int(N).
% XXX inst_ids should include the module.
:- pred write_inst_id(inst_id, io__state, io__state).
:- mode write_inst_id(input, di, uo).
write_inst_id(F - N) -->
prog_out__write_sym_name(F),
io__write_string("/"),
io__write_int(N).
:- pred write_pred_id(pred_id, io__state, io__state).
:- mode write_pred_id(input, di, uo).
/******************** ALL THIS IS COMMENTED OUT
write_pred_id(PredId) -->
% XXX module name
%%% { predicate_module(PredId, Module) },
{ predicate_name(PredId, Name) },
{ predicate_arity(PredId, Arity) },
%%% io__write_string(Module),
%%% io__write_string(":"),
io__write_string(Name),
io__write_string("/"),
io__write_int(Arity).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% builtin_mode(Term, Mode)
% is true iff 'Term' is a constant of the builtin mode 'Mode'.
:- pred builtin_mode(const, string).
:- mode builtin_mode(input, output).
builtin_mode(term_integer(_), "int").
builtin_mode(term_float(_), "float").
builtin_mode(term_string(_), "string").
builtin_mode(term_atom(String), "character") :-
string__char_to_string(_, String).
% is_builtin_mode(ModeId)
% is true iff 'ModeId' is the mode_id of a builting mode
:- pred is_builtin_mode(mode_id).
:- mode is_builtin_mode(input).
is_builtin_mode(unqualified("int") - 0).
is_builtin_mode(unqualified("float") - 0).
is_builtin_mode(unqualified("string") - 0).
is_builtin_mode(unqualified("character") - 0).
is_builtin_mode(qualified(_,"int") - 0).
is_builtin_mode(qualified(_,"float") - 0).
is_builtin_mode(qualified(_,"string") - 0).
is_builtin_mode(qualified(_,"character") - 0).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% The modeinfo data structure and access predicates.
:- mode tvarset == varset.
:- mode tsubst == map(var, mode).
:- mode mode_info ---> modeinfo(
io__state,
pred_table,
mode_table,
cons_table,
pred_id,
term__context,
int, % XXX this field is never used
varset, % variables
mode_assign_set,
bool % did we find any mode errors?
).
% The normal inst of a mode_info struct: ground, with
% the io_state and the struct itself unique, but with
% multiple references allowed for the other parts.
:- inst uniq_mode_info = bound_unique(
modeinfo(
ground_unique, ground,
ground, ground, ground, ground,
ground, ground, ground, ground
)
).
:- mode modeinfo_di :: uniq_mode_info -> dead.
:- mode modeinfo_uo :: free -> uniq_mode_info.
% Some fiddly modes used when we want to extract
% the io_state from a modeinfo struct and then put it back again.
:- inst mode_info_no_io = bound_unique(
modeinfo(
dead, ground,
ground, ground, ground, ground,
ground, ground, ground, ground
)
).
:- mode modeinfo_get_io_state :: uniq_mode_info -> mode_info_no_io.
:- mode modeinfo_set_io_state :: mode_info_no_io -> dead.
%-----------------------------------------------------------------------------%
:- pred modeinfo_init(io__state, module_info, pred_id, term__context,
varset, varset, mode_info).
:- mode modeinfo_init(di, input, input, input, input, input, modeinfo_uo).
modeinfo_init(IOState, ModuleInfo, PredId, Context, ModeVarSet, VarSet,
ModeInfo) :-
moduleinfo_preds(ModuleInfo, Preds),
moduleinfo_modes(ModuleInfo, Modes),
moduleinfo_ctors(ModuleInfo, Ctors),
map__init(ModeBindings),
map__init(VarModes),
ModeInfo = modeinfo(
IOState, Preds, Modes, Ctors, PredId, Context, 0,
VarSet, [mode_assign(VarModes, ModeVarSet, ModeBindings)],
no
).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_io_state(mode_info, io__state).
:- mode modeinfo_get_io_state(modeinfo_get_io_state, uo).
modeinfo_get_io_state(modeinfo(IOState,_,_,_,_,_,_,_,_,_), IOState).
%-----------------------------------------------------------------------------%
:- pred modeinfo_set_io_state(mode_info, io__state, mode_info).
:- mode modeinfo_set_io_state(modeinfo_set_io_state, ui, modeinfo_uo).
modeinfo_set_io_state( modeinfo(_,B,C,D,E,F,G,H,I,J), IOState,
modeinfo(IOState,B,C,D,E,F,G,H,I,J)).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_preds(mode_info, pred_table).
:- mode modeinfo_get_preds(input, output).
modeinfo_get_preds(modeinfo(_,Preds,_,_,_,_,_,_,_,_), Preds).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_modes(mode_info, mode_table).
:- mode modeinfo_get_modes(input, output).
modeinfo_get_modes(modeinfo(_,_,Modes,_,_,_,_,_,_,_), Modes).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_ctors(mode_info, cons_table).
:- mode modeinfo_get_ctors(input, output).
modeinfo_get_ctors(modeinfo(_,_,_,Ctors,_,_,_,_,_,_), Ctors).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_predid(mode_info, pred_id).
:- mode modeinfo_get_predid(input, output).
modeinfo_get_predid(modeinfo(_,_,_,_,PredId,_,_,_,_,_), PredId).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_context(mode_info, term__context).
:- mode modeinfo_get_context(input, output).
modeinfo_get_context(modeinfo(_,_,_,_,_,Context,_,_,_,_), Context).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_varset(mode_info, varset).
:- mode modeinfo_get_varset(input, output).
modeinfo_get_varset(modeinfo(_,_,_,_,_,_,_,VarSet,_,_), VarSet).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_mode_assign_set(mode_info, mode_assign_set).
:- mode modeinfo_get_mode_assign_set(input, output).
modeinfo_get_mode_assign_set(modeinfo(_,_,_,_,_,_,_,_,ModeAssignSet,_),
ModeAssignSet).
%-----------------------------------------------------------------------------%
:- pred modeinfo_set_mode_assign_set(mode_info, mode_assign_set, mode_info).
:- mode modeinfo_set_mode_assign_set(modeinfo_di, input, modeinfo_uo).
modeinfo_set_mode_assign_set( modeinfo(A,B,C,D,E,F,G,H,_,J), ModeAssignSet,
modeinfo(A,B,C,D,E,F,G,H,ModeAssignSet,J)).
%-----------------------------------------------------------------------------%
:- pred modeinfo_set_found_error(mode_info, bool, mode_info).
:- mode modeinfo_set_found_error(modeinfo_di, input, modeinfo_uo).
modeinfo_set_found_error( modeinfo(A,B,C,D,E,F,G,H,I,_), FoundError,
modeinfo(A,B,C,D,E,F,G,H,I,FoundError)).
%-----------------------------------------------------------------------------%
:- pred modeinfo_get_ctor_list(mode_info, const, int, list(hlds__cons_defn)).
:- mode modeinfo_get_ctor_list(input, input, input, output).
modeinfo_get_ctor_list(ModeInfo, Functor, Arity, ConsDefnList) :-
modeinfo_get_ctors(ModeInfo, Ctors),
(
Functor = term_atom(Name),
map__search(Ctors, cons(Name, Arity), ConsDefnList0)
->
ConsDefnList1 = ConsDefnList0
;
ConsDefnList1 = []
),
(
Arity = 0,
builtin_mode(Functor, BuiltInMode)
->
term__context_init("<builtin>", 0, Context),
ModeId = unqualified(BuiltInMode) - 0,
ConsDefn = hlds__cons_defn([], ModeId, Context),
ConsDefnList = [ConsDefn | ConsDefnList1]
;
ConsDefnList = ConsDefnList1
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% The mode_assign and mode_assign_set data structures.
:- mode mode_assign_set == list(mode_assign).
:- mode mode_assign ---> mode_assign(
map(var, mode), % var modes
tvarset, % mode names
tsubst % mode bindings
).
%-----------------------------------------------------------------------------%
% Access predicates for the mode_assign data structure.
% Excruciatingly boring code.
:- pred mode_assign_get_var_modes(mode_assign, map(var, mode)).
:- mode mode_assign_get_var_modes(input, output).
mode_assign_get_var_modes(mode_assign(VarModes, _, _), VarModes).
%-----------------------------------------------------------------------------%
:- pred mode_assign_get_modevarset(mode_assign, tvarset).
:- mode mode_assign_get_modevarset(input, output).
mode_assign_get_modevarset(mode_assign(_, ModeVarSet, _), ModeVarSet).
%-----------------------------------------------------------------------------%
:- pred mode_assign_get_mode_bindings(mode_assign, tsubst).
:- mode mode_assign_get_mode_bindings(input, output).
mode_assign_get_mode_bindings(mode_assign(_, _, ModeBindings), ModeBindings).
%-----------------------------------------------------------------------------%
:- pred mode_assign_set_var_modes(mode_assign, map(var, mode), mode_assign).
:- mode mode_assign_set_var_modes(input, input, output).
mode_assign_set_var_modes(mode_assign(_, B, C), VarModes,
mode_assign(VarModes, B, C)).
%-----------------------------------------------------------------------------%
:- pred mode_assign_set_modevarset(mode_assign, tvarset, mode_assign).
:- mode mode_assign_set_modevarset(input, input, output).
mode_assign_set_modevarset(mode_assign(A, _, C), ModeVarSet,
mode_assign(A, ModeVarSet, C)).
%-----------------------------------------------------------------------------%
:- pred mode_assign_set_mode_bindings(mode_assign, tsubst, mode_assign).
:- mode mode_assign_set_mode_bindings(input, input, output).
mode_assign_set_mode_bindings(mode_assign(A, B, _), ModeBindings,
mode_assign(A, B, ModeBindings)).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% The next section contains predicates for writing error diagnostics.
%-----------------------------------------------------------------------------%
:- pred report_error_unif(pred_id, term__context, varset, term, term,
mode_assign_set, io__state, io__state).
:- mode report_error_unif(input, input, input, input, input, input, di, uo).
report_error_unif(PredId, Context, VarSet, X, Y, ModeAssignSet) -->
write_context_and_predid(Context, PredId),
prog_out__write_context(Context),
io__write_string("mode error in unification of `"),
io__write_term(VarSet, X),
io__write_string("' and `"),
io__write_term(VarSet, Y),
io__write_string("'.\n"),
write_mode_assign_set_msg(ModeAssignSet, VarSet).
%-----------------------------------------------------------------------------%
:- pred write_mode_assign_set_msg(mode_assign_set, tvarset,
io__state, io__state).
:- mode write_mode_assign_set_msg(input, input, di, uo).
write_mode_assign_set_msg(ModeAssignSet, VarSet) -->
( { ModeAssignSet = [_] } ->
io__write_string("\tThe partial mode assignment was:\n")
;
io__write_string("\tThe possible partial mode assignments were:\n")
),
write_mode_assign_set(ModeAssignSet, VarSet).
%-----------------------------------------------------------------------------%
:- pred write_mode_assign_set(mode_assign_set, tvarset, io__state, io__state).
:- mode write_mode_assign_set(input, input, di, uo).
write_mode_assign_set([], _) --> [].
write_mode_assign_set([ModeAssign | ModeAssigns], VarSet) -->
io__write_string("\t"),
write_mode_assign(ModeAssign, VarSet),
write_mode_assign_set(ModeAssigns, VarSet).
:- pred write_mode_assign(mode_assign, tvarset, io__state, io__state).
:- mode write_mode_assign(input, input, di, uo).
write_mode_assign(ModeAssign, VarSet) -->
{
mode_assign_get_var_modes(ModeAssign, VarModes),
mode_assign_get_mode_bindings(ModeAssign, ModeBindings),
mode_assign_get_modevarset(ModeAssign, ModeVarSet),
map__keys(VarModes, Vars),
Vars = [Var | Vars1]
},
(
{ map__search(VarModes, Var, Mode) },
{ varset__lookup_name(VarSet, Var, _) }
->
io__write_variable(Var, VarSet),
io__write_string(" :: "),
write_mode_b(Mode, ModeVarSet, ModeBindings)
;
[]
),
write_mode_assign_2(Vars1, VarSet, VarModes, ModeBindings, ModeVarSet),
io__write_string("\n").
:- pred write_mode_assign_2(list(var), varset, map(var, mode),
tsubst, tvarset, io__state, io__state).
:- mode write_mode_assign_2(input, input, input, input, input, di, uo).
write_mode_assign_2([], _, _, _, _) --> [].
write_mode_assign_2([Var | Vars], VarSet, VarModes, ModeBindings, ModeVarSet)
-->
(
{ map__search(VarModes, Var, Mode) },
{ varset__lookup_name(VarSet, Var, _) }
->
io__write_string(", "),
io__write_variable(Var, VarSet),
io__write_string(" :: "),
write_mode_b(Mode, ModeVarSet, ModeBindings)
;
[]
),
write_mode_assign_2(Vars, VarSet, VarModes, ModeBindings, ModeVarSet).
% write_mode_b writes out a mode after applying the mode bindings.
:- pred write_mode_b(mode, tvarset, tsubst, io__state, io__state).
:- mode write_mode_b(input, input, input, di, uo).
write_mode_b(Mode, ModeVarSet, ModeBindings) -->
{ term__apply_rec_substitution(Mode, ModeBindings, Mode2) },
io__write_term(ModeVarSet, Mode2).
%-----------------------------------------------------------------------------%
:- pred report_error_var(pred_id, term__context, varset, var,
list(mode_stuff), mode, mode_assign_set,
io__state, io__state).
:- mode report_error_var(input, input, input, input, input, input, input,
di, uo).
report_error_var(PredId, Context, VarSet, VarId, ModeStuffList, Mode,
ModeAssignSet0) -->
write_context_and_predid(Context, PredId),
prog_out__write_context(Context),
io__write_string("mode error: "),
io__write_string("variable `"),
io__write_variable(VarId, VarSet),
( { ModeStuffList = [SingleModeStuff] } ->
{ SingleModeStuff = mode_stuff(VMode, TVarSet, TBinding) },
io__write_string("' has mode `"),
write_mode_b(VMode, TVarSet, TBinding),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string("expected mode was `"),
write_mode_b(Mode, TVarSet, TBinding),
io__write_string("'.\n")
;
io__write_string("' has overloaded mode { `"),
write_mode_stuff_list(ModeStuffList),
io__write_string(" },\n"),
io__write_string("which doesn't match the expected mode.\n")
% XXX improve error message: should output
% the expected mode.
),
write_mode_assign_set_msg(ModeAssignSet0, VarSet).
:- pred write_mode_stuff_list(list(mode_stuff), io__state, io__state).
:- mode write_mode_stuff_list(input, di, uo).
write_mode_stuff_list([]) --> [].
write_mode_stuff_list([mode_stuff(T, TVarSet, TBinding) | Ts]) -->
write_mode_b(T, TVarSet, TBinding),
write_mode_stuff_list_2(Ts).
:- pred write_mode_stuff_list_2(list(mode_stuff), io__state, io__state).
:- mode write_mode_stuff_list_2(input, di, uo).
write_mode_stuff_list_2([]) --> [].
write_mode_stuff_list_2([mode_stuff(T, TVarSet, TBinding) | Ts]) -->
io__write_string(", "),
write_mode_b(T, TVarSet, TBinding),
write_mode_stuff_list_2(Ts).
%-----------------------------------------------------------------------------%
:- pred report_error_undef_pred(pred_id, term__context, pred_id,
io__state, io__state).
:- mode report_error_undef_pred(input, input, input, di, uo).
report_error_undef_pred(CallingPredId, Context, PredId) -->
write_context_and_predid(Context, CallingPredId),
prog_out__write_context(Context),
io__write_string("error: undefined predicate `"),
write_pred_id(PredId),
io__write_string("'.\n").
:- pred report_error_undef_cons(pred_id, term__context, const, int,
io__state, io__state).
:- mode report_error_undef_cons(input, input, input, input, di, uo).
report_error_undef_cons(PredId, Context, Functor, Arity) -->
write_context_and_predid(Context, PredId),
prog_out__write_context(Context),
io__write_string("error: undefined symbol `"),
io__write_constant(Functor),
io__write_string("/"),
io__write_int(Arity),
io__write_string("'.\n").
:- pred report_error_cons(pred_id, term__context, varset, const, list(term),
mode, mode_assign_set, io__state, io__state).
:- mode report_error_cons(input, input, input, input, input, input, input,
di, uo).
report_error_cons(PredId, Context, VarSet, Functor, Args, Mode,
ModeAssignSet) -->
write_context_and_predid(Context, PredId),
prog_out__write_context(Context),
io__write_string("mode error: term `"),
io__write_term(VarSet, term_functor(Functor, Args, Context)),
io__write_string("' does not have mode `"),
write_mode(Mode), % XXX
io__write_string("'.\n"),
write_mode_assign_set_msg(ModeAssignSet, VarSet).
%-----------------------------------------------------------------------------%
:- pred write_context_and_predid(term__context, pred_id, io__state, io__state).
:- mode write_context_and_predid(input, input, di, uo).
write_context_and_predid(Context, PredId) -->
prog_out__write_context(Context),
io__write_string("In clause for predicate `"),
write_pred_id(PredId),
io__write_string("':\n").
%-----------------------------------------------------------------------------%
:- pred report_ambiguity_error(mode_info, mode_assign, mode_assign,
io__state, io__state).
:- mode report_ambiguity_error(input, input, input, di, uo).
report_ambiguity_error(ModeInfo, ModeAssign1, ModeAssign2) -->
{ modeinfo_get_context(ModeInfo, Context) },
{ modeinfo_get_predid(ModeInfo, PredId) },
write_context_and_predid(Context, PredId),
prog_out__write_context(Context),
io__write_string("error: ambiguous overloading causes mode ambiguity.\n"),
io__write_string("\tpossible mode assignments include:\n"),
{ modeinfo_get_varset(ModeInfo, VarSet) },
{ mode_assign_get_var_modes(ModeAssign1, VarModes1) },
{ map__keys(VarModes1, Vars1) },
report_ambiguity_error_2(Vars1, VarSet, ModeAssign1, ModeAssign2).
:- pred report_ambiguity_error_2(list(var), varset, mode_assign, mode_assign,
io__state, io__state).
:- mode report_ambiguity_error_2(input, input, input, input, di, uo).
report_ambiguity_error_2([], _VarSet, _ModeAssign1, _ModeAssign2) --> [].
report_ambiguity_error_2([V | Vs], VarSet, ModeAssign1, ModeAssign2) -->
{ mode_assign_get_var_modes(ModeAssign1, VarModes1) },
{ mode_assign_get_var_modes(ModeAssign2, VarModes2) },
( {
map__search(VarModes1, V, T1),
map__search(VarModes2, V, T2),
not (T1 = T2)
} ->
io__write_string("\t"),
io__write_variable(V, VarSet),
io__write_string(" :: "),
{ mode_assign_get_modevarset(ModeAssign1, TVarSet1) },
{ mode_assign_get_mode_bindings(ModeAssign1, ModeBindings1) },
write_mode_b(T1, TVarSet1, ModeBindings1),
io__write_string(" OR "),
{ mode_assign_get_modevarset(ModeAssign2, TVarSet2) },
{ mode_assign_get_mode_bindings(ModeAssign2, ModeBindings2) },
write_mode_b(T2, TVarSet2, ModeBindings2),
io__write_string("\n")
;
[]
),
report_ambiguity_error_2(Vs, VarSet, ModeAssign1, ModeAssign2).
:- pred write_mode(mode, io__state, io__state).
:- mode write_mode(input, di, uo).
write_mode(Mode) -->
{ varset__init(TVarSet) }, % XXX mode parameter names
io__write_term(TVarSet, Mode).
ALL THIS IS COMMENTED OUT ********************/
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%