diff: mode inference & mostly uniq modes
Fergus Henderson
fjh at cs.mu.oz.au
Mon Nov 24 04:07:47 AEDT 1997
Change unique mode analysis (unique_modes.m) so that it does the same
fixpoint analysis that ordinary mode analysis (modes.m) does.
This is a first step towards mode inference of "mostly-unique" modes.
Unique mode analysis still won't introduce any new modes, but it may
now change the final insts of inferred modes from `unique' to `mostly_unique'.
The next step (not included in this diff) will be to change the handling of
calls in unique_modes.m so that it does introduce new modes.
compiler/modes.m:
Add an extra WhatToCheck parameter to lots of predicates,
so they can also be used for checking unique modes.
Add a few small new bits of code to handle the
`WhatToCheck = check_unique_modes' case.
Also change things so that the inferred modes are normally
printed only after unique mode analysis, with determinism
annotations attached.
compiler/unique_modes.m:
Call the routines in modes.m rather than special casing things.
The checking of goals is still special-cased, since for
example unique_modes does not do reordering, but the traversal
of modules and procedures now uses code from modes.m.
compiler/mode_errors.m:
Add an extra bool parameter to write_mode_inference_messages
indicating whether or not to print determinism annotations.
tests/valid/Mmakefile:
tests/valid/mostly_uniq_mode_inf.m:
Test case for the above change.
cvs diff -N compiler/mode_errors.m compiler/modes.m compiler/unique_modes.m tests/valid/Mmakefile tests/valid/mostly_uniq_mode_inf.m
Index: compiler/mode_errors.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_errors.m,v
retrieving revision 1.48
diff -u -r1.48 mode_errors.m
--- mode_errors.m 1997/11/23 05:18:24 1.48
+++ mode_errors.m 1997/11/23 16:56:44
@@ -135,11 +135,14 @@
:- pred mode_context_init(mode_context).
:- mode mode_context_init(out) is det.
- % write out the inferred `mode' declarations for a list of pred_ids.
+ % Write out the inferred `mode' declarations for a list of pred_ids.
+ % The bool indicates whether or not to write out determinism
+ % annotations on the modes (it should only be set to `yes' _after_
+ % determinism analysis).
-:- pred write_mode_inference_messages(list(pred_id), module_info,
+:- pred write_mode_inference_messages(list(pred_id), bool, module_info,
io__state, io__state).
-:- mode write_mode_inference_messages(in, in, di, uo) is det.
+:- mode write_mode_inference_messages(in, in, in, di, uo) is det.
% report an error for the case when two mode declarations
% declare indistinguishable modes
@@ -822,47 +825,54 @@
% write out the inferred `mode' declarations for a list of pred_ids.
-write_mode_inference_messages([], _) --> [].
-write_mode_inference_messages([PredId | PredIds], ModuleInfo) -->
+write_mode_inference_messages([], _, _) --> [].
+write_mode_inference_messages([PredId | PredIds], OutputDetism, ModuleInfo) -->
{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
{ pred_info_get_marker_list(PredInfo, Markers) },
( { list__member(request(infer_modes), Markers) } ->
{ pred_info_procedures(PredInfo, Procs) },
{ map__keys(Procs, ProcIds) },
- write_mode_inference_messages_2(ProcIds, Procs, PredInfo)
+ write_mode_inference_messages_2(ProcIds, Procs, PredInfo,
+ OutputDetism)
;
[]
),
- write_mode_inference_messages(PredIds, ModuleInfo).
+ write_mode_inference_messages(PredIds, OutputDetism, ModuleInfo).
% write out the inferred `mode' declarations for a list of
% proc_ids
:- pred write_mode_inference_messages_2(list(proc_id), proc_table, pred_info,
- io__state, io__state).
-:- mode write_mode_inference_messages_2(in, in, in, di, uo) is det.
+ bool, io__state, io__state).
+:- mode write_mode_inference_messages_2(in, in, in, in, di, uo) is det.
-write_mode_inference_messages_2([], _, _) --> [].
-write_mode_inference_messages_2([ProcId | ProcIds], Procs, PredInfo) -->
+write_mode_inference_messages_2([], _, _, _) --> [].
+write_mode_inference_messages_2([ProcId | ProcIds], Procs, PredInfo,
+ OutputDetism) -->
{ map__lookup(Procs, ProcId, ProcInfo) },
- write_mode_inference_message(PredInfo, ProcInfo),
- write_mode_inference_messages_2(ProcIds, Procs, PredInfo).
+ write_mode_inference_message(PredInfo, ProcInfo, OutputDetism),
+ write_mode_inference_messages_2(ProcIds, Procs, PredInfo, OutputDetism).
% write out the inferred `mode' declaration
% for a single function or predicate.
-:- pred write_mode_inference_message(pred_info, proc_info,
+:- pred write_mode_inference_message(pred_info, proc_info, bool,
io__state, io__state).
-:- mode write_mode_inference_message(in, in, di, uo) is det.
+:- mode write_mode_inference_message(in, in, in, di, uo) is det.
-write_mode_inference_message(PredInfo, ProcInfo) -->
+write_mode_inference_message(PredInfo, ProcInfo, OutputDetism) -->
{ pred_info_name(PredInfo, PredName) },
{ Name = unqualified(PredName) },
{ pred_info_context(PredInfo, Context) },
{ proc_info_argmodes(ProcInfo, Modes0) },
{ varset__init(VarSet) },
{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
- { MaybeDet = no },
+ ( { OutputDetism = yes } ->
+ { proc_info_inferred_determinism(ProcInfo, Detism) },
+ { MaybeDet = yes(Detism) }
+ ;
+ { MaybeDet = no }
+ ),
prog_out__write_context(Context),
{ strip_builtin_qualifiers_from_mode_list(Modes0, Modes) },
io__write_string("Inferred "),
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.207
diff -u -r1.207 modes.m
--- modes.m 1997/11/23 05:18:27 1.207
+++ modes.m 1997/11/23 16:49:43
@@ -144,11 +144,17 @@
:- pred modecheck(module_info, module_info, bool, io__state, io__state).
:- mode modecheck(in, out, out, di, uo) is det.
- % Mode-check the code for single predicate.
-
-:- pred modecheck_pred_mode(pred_id, pred_info, module_info, module_info,
- int, io__state, io__state).
-:- mode modecheck_pred_mode(in, in, in, out, out, di, uo) is det.
+ % Mode-check or unique-mode-check the code for all the predicates
+ % in a module.
+:- pred check_pred_modes(how_to_check_goal, module_info, module_info, bool,
+ io__state, io__state).
+:- mode check_pred_modes(in, in, out, out, di, uo) is det.
+
+ % Mode-check or unique-mode-check the code for single predicate.
+
+:- pred modecheck_pred_mode(pred_id, pred_info, how_to_check_goal,
+ module_info, module_info, int, io__state, io__state).
+:- mode modecheck_pred_mode(in, in, in, in, out, out, di, uo) is det.
% Mode-check the code for predicate in a given mode.
@@ -156,6 +162,16 @@
io__state, io__state).
:- mode modecheck_proc(in, in, in, out, out, di, uo) is det.
+ % Mode-check or unique-mode-check the code for predicate in a
+ % given mode.
+
+:- pred modecheck_proc(proc_id, pred_id, how_to_check_goal,
+ module_info, module_info, int,
+ io__state, io__state).
+:- mode modecheck_proc(in, in, in, in, out, out, di, uo) is det.
+
+ % Mode-check the code for predicate in a given mode.
+
:- pred modecheck_proc_info(proc_id, pred_id, module_info, proc_info,
module_info, proc_info, int, io__state, io__state).
:- mode modecheck_proc_info(in, in, in, in, out, out, out, di, uo) is det.
@@ -289,7 +305,7 @@
io__set_output_stream(StdErr, OldStream),
maybe_write_string(Verbose, "% Mode-checking clauses...\n"),
- check_pred_modes(Module0, Module, UnsafeToContinue),
+ check_pred_modes(check_modes, Module0, Module, UnsafeToContinue),
maybe_report_stats(Statistics),
io__set_output_stream(OldStream, _).
@@ -298,29 +314,39 @@
% 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(in, out, out, di, uo) is det.
-
-check_pred_modes(ModuleInfo0, ModuleInfo, UnsafeToContinue) -->
+check_pred_modes(WhatToCheck, ModuleInfo0, ModuleInfo, UnsafeToContinue) -->
{ module_info_predids(ModuleInfo0, PredIds) },
globals__io_lookup_int_option(mode_inference_iteration_limit,
MaxIterations),
- modecheck_to_fixpoint(PredIds, MaxIterations, ModuleInfo0,
+ modecheck_to_fixpoint(PredIds, MaxIterations, WhatToCheck, ModuleInfo0,
ModuleInfo1, UnsafeToContinue),
- write_mode_inference_messages(PredIds, ModuleInfo1),
+ ( { WhatToCheck = check_unique_modes },
+ write_mode_inference_messages(PredIds, yes, ModuleInfo1)
+ ; { WhatToCheck = check_modes },
+ ( { UnsafeToContinue = yes } ->
+ write_mode_inference_messages(PredIds, no, ModuleInfo1)
+ ;
+ []
+ )
+ ),
modecheck_unify_procs(check_modes, ModuleInfo1, ModuleInfo).
% Iterate over the list of pred_ids in a module.
-:- pred modecheck_to_fixpoint(list(pred_id), int, module_info,
- module_info, bool, io__state, io__state).
-:- mode modecheck_to_fixpoint(in, in, in, out, out, di, uo) is det.
+:- pred modecheck_to_fixpoint(list(pred_id), int, how_to_check_goal,
+ module_info, module_info, bool, io__state, io__state).
+:- mode modecheck_to_fixpoint(in, in, in, in, out, out, di, uo) is det.
-modecheck_to_fixpoint(PredIds, MaxIterations, ModuleInfo0,
+modecheck_to_fixpoint(PredIds, MaxIterations, WhatToCheck, ModuleInfo0,
ModuleInfo, UnsafeToContinue) -->
- { copy_module_clauses_to_procs(PredIds, ModuleInfo0, ModuleInfo1) },
- modecheck_pred_modes_2(PredIds, ModuleInfo1, ModuleInfo2, no, Changed,
- 0, NumErrors),
+ ( { WhatToCheck = check_modes } ->
+ { copy_module_clauses_to_procs(PredIds, ModuleInfo0,
+ ModuleInfo1) }
+ ;
+ { ModuleInfo1 = ModuleInfo0 }
+ ),
+ modecheck_pred_modes_2(PredIds, WhatToCheck, ModuleInfo1, ModuleInfo2,
+ no, Changed, 0, NumErrors),
% stop if we have reached a fixpoint or found any errors
( { Changed = no ; NumErrors > 0 } ->
{ ModuleInfo = ModuleInfo2 },
@@ -334,14 +360,15 @@
;
globals__io_lookup_bool_option(debug_modes, DebugModes),
( { DebugModes = yes } ->
- write_mode_inference_messages(PredIds,
+ write_mode_inference_messages(PredIds, no,
ModuleInfo2)
;
[]
),
{ MaxIterations1 is MaxIterations - 1 },
modecheck_to_fixpoint(PredIds, MaxIterations1,
- ModuleInfo2, ModuleInfo, UnsafeToContinue)
+ WhatToCheck, ModuleInfo2,
+ ModuleInfo, UnsafeToContinue)
)
).
@@ -360,14 +387,15 @@
io__format("(The current limit is %d iterations.)\n",
[i(MaxIterations)]).
-:- pred modecheck_pred_modes_2(list(pred_id), module_info, module_info,
- bool, bool, int, int, io__state, io__state).
-:- mode modecheck_pred_modes_2(in, in, out,
- in, out, in, out, di, uo) is det.
+:- pred modecheck_pred_modes_2(list(pred_id), how_to_check_goal,
+ module_info, module_info, bool, bool, int, int,
+ io__state, io__state).
+:- mode modecheck_pred_modes_2(in, in, in, out, in, out, in, out, di, uo)
+ is det.
-modecheck_pred_modes_2([], ModuleInfo, ModuleInfo, Changed, Changed,
+modecheck_pred_modes_2([], _, ModuleInfo, ModuleInfo, Changed, Changed,
NumErrors, NumErrors) --> [].
-modecheck_pred_modes_2([PredId | PredIds], ModuleInfo0, ModuleInfo,
+modecheck_pred_modes_2([PredId | PredIds], WhatToCheck, ModuleInfo0, ModuleInfo,
Changed0, Changed, NumErrors0, NumErrors) -->
{ module_info_preds(ModuleInfo0, Preds0) },
{ map__lookup(Preds0, PredId, PredInfo0) },
@@ -380,16 +408,11 @@
{ Changed1 = Changed0 },
{ NumErrors1 = NumErrors0 }
;
- { pred_info_get_marker_list(PredInfo0, Markers) },
- ( { list__member(request(infer_modes), Markers) } ->
- write_pred_progress_message("% Mode-analysing ",
- PredId, ModuleInfo0)
- ;
- write_pred_progress_message("% Mode-checking ",
- PredId, ModuleInfo0)
- ),
- modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0,
- ModuleInfo1, Changed0, Changed1, ErrsInThisPred),
+ write_modes_progress_message(PredId, PredInfo0, ModuleInfo0,
+ WhatToCheck),
+ modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck,
+ ModuleInfo0, ModuleInfo1, Changed0, Changed1,
+ ErrsInThisPred),
{ ErrsInThisPred = 0 ->
ModuleInfo3 = ModuleInfo1
;
@@ -402,55 +425,90 @@
},
{ NumErrors1 is NumErrors0 + ErrsInThisPred }
),
- modecheck_pred_modes_2(PredIds, ModuleInfo3, ModuleInfo,
+ modecheck_pred_modes_2(PredIds, WhatToCheck, ModuleInfo3, ModuleInfo,
Changed1, Changed, NumErrors1, NumErrors).
+:- pred write_modes_progress_message(pred_id, pred_info, module_info,
+ how_to_check_goal, io__state, io__state).
+:- mode write_modes_progress_message(in, in, in, in, di, uo) is det.
+
+write_modes_progress_message(PredId, PredInfo, ModuleInfo, WhatToCheck) -->
+ % { pred_info_get_markers(PredInfo, Markers) },
+ % ( { check_marker(Markers, infer_modes) } ->
+ { pred_info_get_marker_list(PredInfo, Markers) },
+ ( { list__member(request(infer_modes), Markers) } ->
+ ( { WhatToCheck = check_modes },
+ write_pred_progress_message("% Mode-analysing ",
+ PredId, ModuleInfo)
+ ; { WhatToCheck = check_unique_modes },
+ write_pred_progress_message("% Unique-mode-analysing ",
+ PredId, ModuleInfo)
+ )
+ ;
+ ( { WhatToCheck = check_modes },
+ write_pred_progress_message("% Mode-checking ",
+ PredId, ModuleInfo)
+ ; { WhatToCheck = check_unique_modes },
+ write_pred_progress_message("% Unique-mode-checking ",
+ PredId, ModuleInfo)
+ )
+ ).
+
%-----------------------------------------------------------------------------%
% Mode-check the code for single predicate.
-modecheck_pred_mode(PredId, PredInfo0, ModuleInfo0, ModuleInfo, NumErrors) -->
- modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0, ModuleInfo,
- no, _Changed, NumErrors).
-
-:- pred modecheck_pred_mode_2(pred_id, pred_info, module_info, module_info,
- bool, bool, int, io__state, io__state).
-:- mode modecheck_pred_mode_2(in, in, in, out, in, out, out, di, uo) is det.
+modecheck_pred_mode(PredId, PredInfo0, WhatToCheck, ModuleInfo0,
+ ModuleInfo, NumErrors) -->
+ modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck,
+ ModuleInfo0, ModuleInfo, no, _Changed, NumErrors).
+
+:- pred modecheck_pred_mode_2(pred_id, pred_info, how_to_check_goal,
+ module_info, module_info, bool, bool, int,
+ io__state, io__state).
+:- mode modecheck_pred_mode_2(in, in, in, in, out, in, out, out, di, uo) is det.
-modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0, ModuleInfo,
+modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck, ModuleInfo0, ModuleInfo,
Changed0, Changed, NumErrors) -->
{ pred_info_procedures(PredInfo0, Procs0) },
{ map__keys(Procs0, ProcIds) },
- ( { ProcIds = [] } ->
- maybe_report_error_no_modes(PredId, PredInfo0, ModuleInfo0),
- { ModuleInfo = ModuleInfo0 },
- { NumErrors = 0 },
- { Changed = Changed0 }
+ ( { WhatToCheck = check_modes } ->
+ ( { ProcIds = [] } ->
+ maybe_report_error_no_modes(PredId, PredInfo0,
+ ModuleInfo0),
+ { NumErrors0 = 0 }
+ ;
+ check_for_indistinguishable_modes(ProcIds, PredId,
+ PredInfo0, ModuleInfo0, 0, NumErrors0)
+ )
;
- check_for_indistinguishable_modes(ProcIds, PredId, PredInfo0,
- ModuleInfo0, 0, NumErrors0),
- modecheck_procs(ProcIds, PredId, ModuleInfo0, Changed0, 0,
- ModuleInfo, Changed, NumErrors1),
- { NumErrors is NumErrors0 + NumErrors1 }
- ).
+ { NumErrors0 = 0 }
+ ),
+ modecheck_procs(ProcIds, PredId, WhatToCheck,
+ ModuleInfo0, Changed0, NumErrors0,
+ ModuleInfo, Changed, NumErrors).
% Iterate over the list of modes for a predicate.
-:- pred modecheck_procs(list(proc_id), pred_id, module_info, bool, int,
+:- pred modecheck_procs(list(proc_id), pred_id, how_to_check_goal,
+ module_info, bool, int,
module_info, bool, int, io__state, io__state).
-:- mode modecheck_procs(in, in, in, in, in, out, out, out, di, uo) is det.
+:- mode modecheck_procs(in, in, in, in, in, in, out, out, out, di, uo) is det.
-modecheck_procs([], _PredId, ModuleInfo, Changed, Errs,
+modecheck_procs([], _PredId, _, ModuleInfo, Changed, Errs,
ModuleInfo, Changed, Errs) --> [].
-modecheck_procs([ProcId|ProcIds], PredId, ModuleInfo0, Changed0, Errs0,
+modecheck_procs([ProcId|ProcIds], PredId, WhatToCheck,
+ ModuleInfo0, Changed0, Errs0,
ModuleInfo, Changed, Errs) -->
% mode-check that mode of the predicate
- modecheck_proc_2(ProcId, PredId, ModuleInfo0, Changed0,
+ modecheck_proc_2(ProcId, PredId, WhatToCheck,
+ ModuleInfo0, Changed0,
ModuleInfo1, Changed1, NumErrors),
{ Errs1 is Errs0 + NumErrors },
% recursively process the remaining modes
- modecheck_procs(ProcIds, PredId, ModuleInfo1, Changed1,
- Errs1, ModuleInfo, Changed, Errs).
+ modecheck_procs(ProcIds, PredId, WhatToCheck,
+ ModuleInfo1, Changed1, Errs1,
+ ModuleInfo, Changed, Errs).
%-----------------------------------------------------------------------------%
@@ -503,16 +561,22 @@
% Mode-check the code for predicate in a given mode.
modecheck_proc(ProcId, PredId, ModuleInfo0, ModuleInfo, NumErrors) -->
- modecheck_proc_2(ProcId, PredId, ModuleInfo0, no,
+ modecheck_proc(ProcId, PredId, check_modes,
+ ModuleInfo0, ModuleInfo, NumErrors).
+
+modecheck_proc(ProcId, PredId, WhatToCheck, ModuleInfo0,
+ ModuleInfo, NumErrors) -->
+ modecheck_proc_2(ProcId, PredId, WhatToCheck, ModuleInfo0, no,
ModuleInfo, _Changed, NumErrors).
-:- pred modecheck_proc_2(proc_id, pred_id, module_info, bool,
- module_info, bool, int,
+:- pred modecheck_proc_2(proc_id, pred_id, how_to_check_goal,
+ module_info, bool, module_info, bool, int,
io__state, io__state).
-:- mode modecheck_proc_2(in, in, in, in, out, out, out, di, uo) is det.
+:- mode modecheck_proc_2(in, in, in, in, in, out, out, out, di, uo) is det.
-modecheck_proc_2(ProcId, PredId, ModuleInfo0, Changed0,
- ModuleInfo, Changed, NumErrors) -->
+modecheck_proc_2(ProcId, PredId, WhatToCheck,
+ ModuleInfo0, Changed0,
+ ModuleInfo, Changed, NumErrors) -->
% get the proc_info from the module_info
{ module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
_PredInfo0, ProcInfo0) },
@@ -522,7 +586,7 @@
{ NumErrors = 0 }
;
% modecheck it
- modecheck_proc_3(ProcId, PredId,
+ modecheck_proc_3(ProcId, PredId, WhatToCheck,
ModuleInfo0, ProcInfo0, Changed0,
ModuleInfo1, ProcInfo, Changed, NumErrors),
% save the proc_info back in the module_info
@@ -537,18 +601,22 @@
modecheck_proc_info(ProcId, PredId, ModuleInfo0, ProcInfo0,
ModuleInfo, ProcInfo, NumErrors) -->
- modecheck_proc_3(ProcId, PredId, ModuleInfo0, ProcInfo0, no,
- ModuleInfo, ProcInfo, _Changed, NumErrors).
+ { WhatToCheck = check_modes },
+ modecheck_proc_3(ProcId, PredId, WhatToCheck,
+ ModuleInfo0, ProcInfo0, no,
+ ModuleInfo, ProcInfo, _Changed, NumErrors).
-:- pred modecheck_proc_3(proc_id, pred_id, module_info, proc_info, bool,
+:- pred modecheck_proc_3(proc_id, pred_id, how_to_check_goal,
+ module_info, proc_info, bool,
module_info, proc_info, bool, int,
io__state, io__state).
-:- mode modecheck_proc_3(in, in, in, in, in, out, out, out, out, di, uo)
+:- mode modecheck_proc_3(in, in, in, in, in, in, out, out, out, out, di, uo)
is det.
-modecheck_proc_3(ProcId, PredId, ModuleInfo0, ProcInfo0, Changed0,
- ModuleInfo, ProcInfo, Changed, NumErrors,
- IOState0, IOState) :-
+modecheck_proc_3(ProcId, PredId, WhatToCheck,
+ ModuleInfo0, ProcInfo0, Changed0,
+ ModuleInfo, ProcInfo, Changed, NumErrors,
+ IOState0, IOState) :-
% extract the useful fields in the proc_info
proc_info_headvars(ProcInfo0, HeadVars),
proc_info_argmodes(ProcInfo0, ArgModes0),
@@ -567,21 +635,38 @@
proc_info_context(ProcInfo0, Context)
),
- % modecheck the clause - first set the initial instantiation
- % of the head arguments, mode-check the body, and
- % then check that the final instantiation matches that in
- % the mode declaration
+ %
+ % modecheck the clause - first set the initial instantiation
+ % of the head arguments, mode-check the body, and
+ % then check that the final instantiation matches that in
+ % the mode declaration
+ %
+
+ % construct the initial instmap
mode_list_get_initial_insts(ArgModes0, ModuleInfo0, ArgInitialInsts),
assoc_list__from_corresponding_lists(HeadVars, ArgInitialInsts, InstAL),
instmap__from_assoc_list(InstAL, InstMap0),
+
+ % construct the initial set of live vars:
% initially, only the non-clobbered head variables are live
- mode_list_get_final_insts(ArgModes0, ModuleInfo0, ArgFinalInsts0),
get_live_vars(HeadVars, ArgLives0, LiveVarsList),
set__list_to_set(LiveVarsList, LiveVars),
+
+ % initialize the mode info
mode_info_init(IOState0, ModuleInfo0, PredId, ProcId,
Context, LiveVars, InstMap0, ModeInfo0),
mode_info_set_changed_flag(Changed0, ModeInfo0, ModeInfo1),
- modecheck_goal(Body0, Body, ModeInfo1, ModeInfo2),
+
+ % modecheck the procedure body
+ ( WhatToCheck = check_unique_modes ->
+ unique_modes__check_goal(Body0, Body, ModeInfo1, ModeInfo2)
+ ;
+ modecheck_goal(Body0, Body, ModeInfo1, ModeInfo2)
+ ),
+
+ % check that final insts match those specified in the
+ % mode declaration
+ mode_list_get_final_insts(ArgModes0, ModuleInfo0, ArgFinalInsts0),
pred_info_get_marker_list(PredInfo, Markers),
( list__member(request(infer_modes), Markers) ->
InferModes = yes
@@ -590,8 +675,10 @@
),
modecheck_final_insts_2(HeadVars, ArgFinalInsts0, ModeInfo2,
InferModes, ArgFinalInsts, ModeInfo3),
- inst_lists_to_mode_list(ArgInitialInsts, ArgFinalInsts, ArgModes),
+
+ % report any errors we found, and save away the results
report_mode_errors(ModeInfo3, ModeInfo),
+ inst_lists_to_mode_list(ArgInitialInsts, ArgFinalInsts, ArgModes),
mode_info_get_changed_flag(ModeInfo, Changed),
mode_info_get_module_info(ModeInfo, ModuleInfo),
mode_info_get_num_errors(ModeInfo, NumErrors),
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.40
diff -u -r1.40 unique_modes.m
--- unique_modes.m 1997/09/15 21:12:50 1.40
+++ unique_modes.m 1997/11/23 16:01:54
@@ -62,146 +62,18 @@
%-----------------------------------------------------------------------------%
- % This section just traverses the module structure.
-
unique_modes__check_module(ModuleInfo0, ModuleInfo) -->
- { module_info_predids(ModuleInfo0, PredIds) },
- unique_modes__check_preds(PredIds, ModuleInfo0, ModuleInfo1),
- modecheck_unify_procs(check_unique_modes, ModuleInfo1, ModuleInfo).
-
-:- pred unique_modes__check_preds(list(pred_id), module_info, module_info,
- io__state, io__state).
-:- mode unique_modes__check_preds(in, in, out, di, uo) is det.
-
-unique_modes__check_preds([], ModuleInfo, ModuleInfo) --> [].
-unique_modes__check_preds([PredId | PredIds], ModuleInfo0, ModuleInfo) -->
- { module_info_preds(ModuleInfo0, PredTable) },
- { map__lookup(PredTable, PredId, PredInfo) },
- { pred_info_non_imported_procids(PredInfo, ProcIds) },
- ( { ProcIds \= [] } ->
- write_pred_progress_message("% Unique-mode-checking ",
- PredId, ModuleInfo0)
- ;
- []
- ),
- unique_modes__check_procs(ProcIds, PredId, ModuleInfo0, ModuleInfo1),
- unique_modes__check_preds(PredIds, ModuleInfo1, ModuleInfo).
-
-:- pred unique_modes__check_procs(list(proc_id), pred_id,
- module_info, module_info,
- io__state, io__state).
-:- mode unique_modes__check_procs(in, in, in, out, di, uo) is det.
-
-unique_modes__check_procs([], _PredId, ModuleInfo, ModuleInfo) --> [].
-unique_modes__check_procs([ProcId | ProcIds], PredId, ModuleInfo0,
- ModuleInfo) -->
- unique_modes__check_proc(ProcId, PredId, ModuleInfo0, ModuleInfo1),
- unique_modes__check_procs(ProcIds, PredId, ModuleInfo1, ModuleInfo).
+ check_pred_modes(check_unique_modes, ModuleInfo0, ModuleInfo,
+ _UnsafeToContinue).
unique_modes__check_proc(ProcId, PredId, ModuleInfo0, ModuleInfo) -->
- { module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
- _PredInfo0, ProcInfo0) },
- ( { proc_info_can_process(ProcInfo0, no) } ->
- { ModuleInfo = ModuleInfo0 }
+ modecheck_proc(ProcId, PredId, check_unique_modes,
+ ModuleInfo0, ModuleInfo, NumErrors),
+ ( { NumErrors \= 0 } ->
+ io__set_exit_status(1)
;
- unique_modes__check_proc_2(ProcInfo0, PredId, ProcId,
- ModuleInfo0, ProcInfo, ModuleInfo1),
-
- { module_info_preds(ModuleInfo1, PredTable1) },
- { map__lookup(PredTable1, PredId, PredInfo1) },
- { pred_info_procedures(PredInfo1, ProcTable1) },
- { map__set(ProcTable1, ProcId, ProcInfo, ProcTable) },
- { pred_info_set_procedures(PredInfo1, ProcTable, PredInfo) },
- { map__set(PredTable1, PredId, PredInfo, PredTable) },
- { module_info_set_preds(ModuleInfo1, PredTable, ModuleInfo) }
+ []
).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
- % just check a single procedure
-:- pred unique_modes__check_proc_2(proc_info, pred_id, proc_id, module_info,
- proc_info, module_info, io__state, io__state).
-:- mode unique_modes__check_proc_2(in, in, in, in, out, out, di, uo) is det.
-
-unique_modes__check_proc_2(ProcInfo0, PredId, ProcId, ModuleInfo0,
- ProcInfo, ModuleInfo,
- IOState0, IOState) :-
- %
- % Extract the useful fields in the proc_info.
- %
- proc_info_headvars(ProcInfo0, Args),
- proc_info_argmodes(ProcInfo0, ArgModes),
- proc_info_arglives(ProcInfo0, ModuleInfo0, ArgLives),
- proc_info_goal(ProcInfo0, Goal0),
-
- %
- % Figure out the right context to use.
- % We use the context of the first clause, unless
- % there weren't any clauses at all, in which case
- % we use the context of the mode declaration.
- %
- module_info_pred_info(ModuleInfo0, PredId, PredInfo),
- pred_info_clauses_info(PredInfo, ClausesInfo),
- ClausesInfo = clauses_info(_, _, _, _, ClauseList),
- ( ClauseList = [FirstClause | _] ->
- FirstClause = clause(_, _, Context)
- ;
- proc_info_context(ProcInfo0, Context)
- ),
-
- %
- % Construct the initial instmap
- %
- mode_list_get_initial_insts(ArgModes, ModuleInfo0, ArgInitialInsts),
- assoc_list__from_corresponding_lists(Args, ArgInitialInsts, InstAL),
- instmap__from_assoc_list(InstAL, InstMap0),
-
- %
- % Construct the initial set of live variables:
- % initially, only the non-clobbered head variables are live
- %
- get_live_vars(Args, ArgLives, LiveVarsList),
- set__list_to_set(LiveVarsList, LiveVars),
-
- %
- % At last we're ready to construct the initial mode_info
- %
- mode_info_init(IOState0, ModuleInfo0, PredId, ProcId, Context,
- LiveVars, InstMap0, ModeInfo0),
- %
- % Modecheck the goal
- %
- unique_modes__check_goal(Goal0, Goal, ModeInfo0, ModeInfo1),
-
- %
- % Check that the final insts of the head vars is OK
- %
- mode_list_get_final_insts(ArgModes, ModuleInfo0, ArgFinalInsts),
- modecheck_final_insts(Args, ArgFinalInsts, ModeInfo1, ModeInfo2),
-
- %
- % If we encountered any errors then report them
- %
- report_mode_errors(ModeInfo2, ModeInfo),
-
- %
- % Get the info we need from the mode_info and stuff it back
- % in the proc_info
- %
- mode_info_get_module_info(ModeInfo, ModuleInfo),
- mode_info_get_io_state(ModeInfo, IOState1),
- mode_info_get_errors(ModeInfo, Errors),
- ( Errors = [] ->
- IOState = IOState1
- ;
- io__set_exit_status(1, IOState1, IOState)
- ),
- mode_info_get_varset(ModeInfo, VarSet),
- mode_info_get_var_types(ModeInfo, VarTypes),
- proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
- proc_info_set_variables(ProcInfo1, VarSet, ProcInfo2),
- proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo).
% XXX we currently make the conservative assumption that
% any non-local variable in a disjunction or nondet call
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.3
diff -u -r1.3 Mmakefile
--- Mmakefile 1997/11/22 17:14:02 1.3
+++ Mmakefile 1997/11/23 16:32:41
@@ -55,6 +55,7 @@
loop_in_disj.m \
middle_rec_labels.m \
modes_bug.m \
+ mostly_uniq_mode_inf.m \
multidet_prune1.m \
multidet_test.m \
nasty_func_test.m \
@@ -105,6 +106,7 @@
MCFLAGS-higher_order_implied_mode = -O-1
MCFLAGS-livevals_seq = -O5 --opt-space
MCFLAGS-middle_rec_labels = --middle-rec --no-follow-vars
+MCFLAGS-mostly_uniq_mode_inf = --infer-all
MCFLAGS-pred_with_no_modes = --infer-all
MCFLAGS-simplify_bug = -O-1
MCFLAGS-two_way_unif = -O-1
Index: tests/valid/mostly_uniq_mode_inf.m
===================================================================
RCS file: mostly_uniq_mode_inf.m
diff -N mostly_uniq_mode_inf.m
--- /dev/null Mon Nov 24 03:56:44 1997
+++ mostly_uniq_mode_inf.m Mon Nov 24 03:15:58 1997
@@ -0,0 +1,20 @@
+% This module tests inference of mostly-unique modes.
+% The compiler needs to infer mostly-unique modes for foo/2 and foo2/2.
+
+:- module mostly_uniq_mode_inf.
+:- interface.
+:- pred p is semidet.
+
+:- implementation.
+:- import_module int.
+
+p :- foo(42, Z), bar(Z, A), A > 100.
+
+foo(X, Y) :- foo2(X, Y).
+
+foo2(X, Y) :- Y is X + 10.
+foo2(X, Y) :- Y = X.
+
+:- mode bar(mdi, muo) is det.
+bar(X, X).
+
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list