[m-dev.] for review: fix bug in unique mode checking

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Apr 9 05:50:33 AEST 1999


On 09-Apr-1999, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> tests/hard_coded/Mmakefile:
> 	Disable the test case bidirectional.m, since the compiler now
> 	rejects it, due to the above change to unique_modes.m. 
> 	The compiler is again being overly conservative in its analysis.
> 	The problem is similar to that in the two test cases above, 
> 	unfortunately there is no easy work-around in this case. 
> 	The compiler really ought to support this style of bidirectional
> 	code using unique modes, so I do consider this to be a significant
> 	problem, but the fix is a fair bit of work, so I will deal with
> 	that as a separate change.

Actually it turned out to be not so difficult after all.
I think I will still commit it as a separate change, though.

Could someone please review this one too?

--------------------

Estimated hours taken: 1

Perform some minor simplifications in mode analysis,
so as to provide more information to unique mode analysis.
Previously unique_modes.m was reporting spurious errors
for tests/hard_coded/bidirectional.m, because modes.m
produced output containing a subgoal of the form
`disj([Goal, conj([disj([])]])' instead of just `Goal',
and the presence of a disjunction then caused unique mode
analysis to make overly conservative assumptions.

compiler/modes.m:
	Ensure that we do not produce singleton conjunctions or disjunctions.
	Also, if the result of mode checking a disjunct is a (nested)
	disjunction, then merge it with the containing disjunction.
	If the nested disjunction is the empty disjunction (fail),
	then this means it will be deleted.

tests/hard_coded/Mmakefile:
	Re-enable the test case bidirectional.m, since the compiler now
	accepts it, due to the above change.

Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.228
diff -u -r1.228 modes.m
--- modes.m	1998/11/20 04:08:33	1.228
+++ modes.m	1999/04/08 19:39:54
@@ -925,12 +925,13 @@
 	compute_instmap_delta(InstMap0, InstMap, NonLocals, DeltaInstMap),
 	goal_info_set_instmap_delta(GoalInfo0, DeltaInstMap, GoalInfo).
 
-modecheck_goal_expr(conj(List0), _GoalInfo0, conj(List)) -->
+modecheck_goal_expr(conj(List0), GoalInfo0, Goal) -->
 	mode_checkpoint(enter, "conj"),
 	( { List0 = [] } ->	% for efficiency, optimize common case
-		{ List = [] }
+		{ Goal = conj([]) }
 	;
-		modecheck_conj_list(List0, List)
+		modecheck_conj_list(List0, List),
+		{ conj_list_to_goal(List, GoalInfo0, Goal - _GoalInfo) }
 	),
 	mode_checkpoint(exit, "conj").
 
@@ -961,16 +962,17 @@
 	instmap__unify(NonLocals, InstMapNonlocalList),
 	mode_checkpoint(exit, "par_conj").
 
-modecheck_goal_expr(disj(List0, SM), GoalInfo0, disj(List, SM)) -->
+modecheck_goal_expr(disj(List0, SM), GoalInfo0, Goal) -->
 	mode_checkpoint(enter, "disj"),
 	( { List0 = [] } ->	% for efficiency, optimize common case
-		{ List = [] },
+		{ Goal = disj(List0, SM) },
 		{ instmap__init_unreachable(InstMap) },
 		mode_info_set_instmap(InstMap)
 	;
 		{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
 		modecheck_disj_list(List0, List, InstMapList),
-		instmap__merge(NonLocals, InstMapList, disj)
+		instmap__merge(NonLocals, InstMapList, disj),
+		{ disj_list_to_goal(List, GoalInfo0, Goal - _GoalInfo) }
 	),
 	mode_checkpoint(exit, "disj").
 
@@ -1450,12 +1452,19 @@
 :- mode modecheck_disj_list(in, out, out, mode_info_di, mode_info_uo) is det.
 
 modecheck_disj_list([], [], []) --> [].
-modecheck_disj_list([Goal0 | Goals0], [Goal | Goals], [InstMap | InstMaps]) -->
+modecheck_disj_list([Goal0 | Goals0], Goals, [InstMap | InstMaps]) -->
 	mode_info_dcg_get_instmap(InstMap0),
 	modecheck_goal(Goal0, Goal),
 	mode_info_dcg_get_instmap(InstMap),
 	mode_info_set_instmap(InstMap0),
-	modecheck_disj_list(Goals0, Goals, InstMaps).
+	modecheck_disj_list(Goals0, Goals1, InstMaps),
+	%
+	% If Goal is a nested disjunction,
+	% then merge it with the outer disjunction.
+	% If Goal is `fail', this will delete it.
+	%
+	{ goal_to_disj_list(Goal, DisjList) },
+	{ list__append(DisjList, Goals1, Goals) }.
 
 :- pred modecheck_case_list(list(case), prog_var, list(case), list(instmap),
 				mode_info, mode_info).
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.55
diff -u -r1.55 Mmakefile
--- Mmakefile	1999/03/26 04:34:14	1.55
+++ Mmakefile	1999/04/08 17:18:29
@@ -9,7 +9,6 @@
 PROGS=	\
 	address_of_builtins \
 	agg \
+	bidirectional \
 	bigtest \
 	boyer \
 	c_write_string \
@@ -94,6 +93,8 @@
 
 # we do no pass the following tests
 #	var_not_found -- "sorry, not implemented" in polymorphism.m.
-#	bidirectional -- unique mode analysis is overly conservative
-#		and thus rejects this test case.
 
 #-----------------------------------------------------------------------------#
 
-- 
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