for review: bug fix for failure handling

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Aug 5 18:56:24 AEST 1998


This is for Fergus.

Estimated hours taken: 8

Fix a subtle bug in the new way of handling failure. When we enter the
last disjunct of a model_non disjunction inside the model_non condition
of an if-then-else, set resume_point_known to unknown. This forces code
in the last disjunct and after the last disjunction to fail by invoking
redo(), not by a direct branch. The reason this is necessary that a direct
branch to the start of the else case is incorrect if the condition has
already returned some answers.

The bug was causing tests/general/complex_failure to fail at optimization
levels that caused the inlining of a predicate, which resulted in a disjunction
inside the last disjunct of a disjunction inside a model_non condition.

compiler/notes/failure.html:
	Modify the description of failure handling to encompass the solution
	of the problem.

compiler/code_info.m:
	Implement the solution.

tests/general/semi_fail_in_non_ite.{m,exp}:
	Add a new test case, a variant of complex_failure, that tests for the
	bug at all optimization levels.

tests/general/Mmakefile:
	Enable the new test case.

tests/general/complex_failure.m:
	Remove an obsolete comment.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.226
diff -u -u -r1.226 code_info.m
--- code_info.m	1998/07/29 08:52:50	1.226
+++ code_info.m	1998/08/05 08:45:38
@@ -284,7 +284,7 @@
 		Hijack = not_allowed
 	),
 	DummyFailInfo = fail_info(ResumePoints, resume_point_unknown,
-		may_be_different, Hijack),
+		may_be_different, not_inside_non_condition, Hijack),
 	set__init(AvailSlots),
 	map__init(TempsInUse),
 	set__init(Zombies),
@@ -762,7 +762,7 @@
 
 code_info__current_resume_point_vars(ResumeVars) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePointStack, _, _, _) },
+	{ FailInfo = fail_info(ResumePointStack, _, _, _, _) },
 	{ stack__top_det(ResumePointStack, ResumePointInfo) },
 	{ code_info__pick_first_resume_point(ResumePointInfo, ResumeMap, _) },
 	{ map__keys(ResumeMap, ResumeMapVarList) },
@@ -893,8 +893,10 @@
 			% branched structure with is valid for all branches.
 		code_info__get_fail_info(FailInfo0, EndCodeInfo0, _),
 		code_info__get_fail_info(FailInfo1, EndCodeInfo1, _),
-		FailInfo0 = fail_info(_, ResumeKnown0, CurfrMaxfr0, Hijack0),
-		FailInfo1 = fail_info(R, ResumeKnown1, CurfrMaxfr1, Hijack1),
+		FailInfo0 = fail_info(_, ResumeKnown0, CurfrMaxfr0,
+			CondEnv0, Hijack0),
+		FailInfo1 = fail_info(R, ResumeKnown1, CurfrMaxfr1,
+			CondEnv1, Hijack1),
 		(
 			ResumeKnown0 = resume_point_known,
 			ResumeKnown1 = resume_point_known
@@ -919,7 +921,10 @@
 		;
 			Hijack = not_allowed
 		),
-		FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr, Hijack),
+		require(unify(CondEnv0, CondEnv1),
+			"some but not all branches inside a non condition"),
+		FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr,
+			CondEnv0, Hijack),
 		code_info__set_fail_info(FailInfo, EndCodeInfo1, EndCodeInfo)
 	},
 	{ MaybeEnd = yes(branch_end_info(EndCodeInfo)) }.
@@ -1163,6 +1168,7 @@
 			stack(resume_point_info),
 			resume_point_known,
 			curfr_vs_maxfr,
+			condition_env,
 			hijack_allowed
 		).
 
@@ -1195,6 +1201,9 @@
 :- type curfr_vs_maxfr		--->	must_be_equal
 				;	may_be_different.
 
+:- type condition_env		--->	inside_non_condition
+				;	not_inside_non_condition.
+
 :- type hijack_allowed		--->	allowed
 				;	not_allowed.
 
@@ -1217,7 +1226,7 @@
 
 code_info__prepare_for_disj_hijack(CodeModel, HijackInfo, Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, Allow) },
+	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, CondEnv, Allow) },
 	(
 		{ CodeModel \= model_non }
 	->
@@ -1227,7 +1236,7 @@
 				- ""
 		]) }
 	;
-		{ Allow = not_allowed }
+		{ Allow = not_allowed ; CondEnv = inside_non_condition }
 	->
 		{ HijackInfo = disj_temp_frame },
 		code_info__create_temp_frame(do_fail,
@@ -1270,8 +1279,9 @@
 	).
 
 code_info__undo_disj_hijack(HijackInfo, Code) -->
-	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, _) },
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
+		CondEnv, Allow) },
 	(
 		{ HijackInfo = disj_no_hijack },
 		{ Code = empty }
@@ -1315,6 +1325,18 @@
 			assign(redofr(lval(maxfr)), lval(RedofrSlot))
 				- "restore redofr for full disj hijack"
 		]) }
+	),
+	(
+			% HijackInfo \= disj_no_hijack if and only if
+			% the disjunction is model_non.
+		{ HijackInfo \= disj_no_hijack },
+		{ CondEnv = inside_non_condition }
+	->
+		{ FailInfo = fail_info(ResumePoints, resume_point_unknown,
+			CurfrMaxfr, CondEnv, Allow) },
+		code_info__set_fail_info(FailInfo)
+	;
+		[]
 	).
 
 %---------------------------------------------------------------------------%
@@ -1322,7 +1344,7 @@
 :- type ite_hijack_info
 	--->	ite_info(
 			resume_point_known,
-			hijack_allowed,
+			condition_env,
 			ite_hijack_type
 		).
 
@@ -1348,7 +1370,7 @@
 
 code_info__prepare_for_ite_hijack(EffCodeModel, HijackInfo, Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, Allow) },
+	{ FailInfo = fail_info(_, ResumeKnown, CurfrMaxfr, CondEnv, Allow) },
 	(
 		{ EffCodeModel \= model_non }
 	->
@@ -1358,7 +1380,7 @@
 				- ""
 		]) }
 	;
-		{ Allow = not_allowed }
+		{ Allow = not_allowed ; CondEnv = inside_non_condition }
 	->
 		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
 		{ HijackType = ite_temp_frame(MaxfrSlot) },
@@ -1410,15 +1432,19 @@
 				- "prepare for full ite hijack"
 		]) }
 	),
-	{ HijackInfo = ite_info(ResumeKnown, Allow, HijackType) },
-	code_info__disallow_hijack.
+	{ HijackInfo = ite_info(ResumeKnown, CondEnv, HijackType) },
+	( { EffCodeModel = model_non } ->
+		code_info__inside_non_condition
+	;
+		[]
+	).
 
 code_info__ite_enter_then(HijackInfo, ThenCode, ElseCode) -->
 	code_info__get_fail_info(FailInfo0),
 	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown0, CurfrMaxfr,
-		_) },
+		_, Allow) },
 	{ stack__pop_det(ResumePoints0, _, ResumePoints) },
-	{ HijackInfo = ite_info(ResumeKnown1, Allow1, HijackType) },
+	{ HijackInfo = ite_info(ResumeKnown1, OldCondEnv, HijackType) },
 	{
 		HijackType = ite_no_hijack,
 		ThenCode = empty,
@@ -1485,7 +1511,7 @@
 		ResumeKnown = resume_point_unknown
 	},
 	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
-		Allow1) },
+		OldCondEnv, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
@@ -1537,7 +1563,7 @@
 
 code_info__prepare_for_det_commit(DetCommitInfo, Code) -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(_, _, CurfrMaxfr, _) },
+	{ FailInfo0 = fail_info(_, _, CurfrMaxfr, _, _) },
 	(
 		{ CurfrMaxfr = may_be_different },
 		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
@@ -1608,17 +1634,18 @@
 code_info__prepare_for_semi_commit(SemiCommitInfo, Code) -->
 	code_info__get_fail_info(FailInfo0),
 	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown, CurfrMaxfr,
-		Allow) },
+		CondEnv, Allow) },
 	{ stack__top_det(ResumePoints0, TopResumePoint) },
 	code_info__clone_resume_point(TopResumePoint, NewResumePoint),
 	{ stack__push(ResumePoints0, NewResumePoint, ResumePoints) },
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, Allow) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
+		CondEnv, Allow) },
 	code_info__set_fail_info(FailInfo),
 
 	{ code_info__pick_stack_resume_point(NewResumePoint, _, StackLabel) },
 	{ StackLabelConst = const(code_addr_const(StackLabel)) },
 	(
-		{ Allow = not_allowed }
+		{ Allow = not_allowed ; CondEnv = inside_non_condition }
 	->
 		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
 		{ HijackInfo = commit_temp_frame(MaxfrSlot) },
@@ -1692,7 +1719,7 @@
 		{ FailureUndoCode = SuccessUndoCode }
 	;
 		{ HijackInfo = commit_quarter_hijack },
-		{ FailInfo = fail_info(ResumePoints, _, _, _) },
+		{ FailInfo = fail_info(ResumePoints, _, _, _, _) },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
 		{ code_info__pick_stack_resume_point(TopResumePoint,
 			_, StackLabel) },
@@ -1772,13 +1799,14 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred code_info__disallow_hijack(code_info::in, code_info::out) is det.
+:- pred code_info__inside_non_condition(code_info::in, code_info::out) is det.
 
-code_info__disallow_hijack -->
+code_info__inside_non_condition -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr, _) },
+	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
+		_, Allow) },
 	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr,
-		not_allowed) },
+		inside_non_condition, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 :- pred code_info__create_temp_frame(code_addr::in, string::in, code_tree::out,
@@ -1796,9 +1824,9 @@
 			- Comment
 	]) },
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, _, Allow) },
+	{ FailInfo0 = fail_info(ResumePoints, ResumeKnown, _, CondEnv, Allow) },
 	{ FailInfo = fail_info(ResumePoints, ResumeKnown, may_be_different,
-		Allow) },
+		CondEnv, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
@@ -1806,7 +1834,7 @@
 code_info__effect_resume_point(ResumePoint, CodeModel, Code) -->
 	code_info__get_fail_info(FailInfo0),
 	{ FailInfo0 = fail_info(ResumePoints0, _ResumeKnown, CurfrMaxfr,
-		Allow) },
+		CondEnv, Allow) },
 
 	{ stack__top(ResumePoints0, OldResumePoint) ->
 		code_info__pick_first_resume_point(OldResumePoint, OldMap, _),
@@ -1823,7 +1851,7 @@
 
 	{ stack__push(ResumePoints0, ResumePoint, ResumePoints) },
 	{ FailInfo = fail_info(ResumePoints, resume_point_known, CurfrMaxfr,
-		Allow) },
+		CondEnv, Allow) },
 	code_info__set_fail_info(FailInfo),
 	( { CodeModel = model_non } ->
 		{ code_info__pick_stack_resume_point(ResumePoint,
@@ -1841,28 +1869,28 @@
 
 code_info__top_resume_point(ResumePoint) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, _, _, _) },
+	{ FailInfo = fail_info(ResumePoints, _, _, _, _) },
 	{ stack__top_det(ResumePoints, ResumePoint) }.
 
 code_info__set_resume_point_to_unknown -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, _, CurfrMaxfr, Allow) },
+	{ FailInfo0 = fail_info(ResumePoints, _, CurfrMaxfr, CondEnv, Allow) },
 	{ FailInfo = fail_info(ResumePoints, resume_point_unknown,
-		CurfrMaxfr, Allow) },
+		CurfrMaxfr, CondEnv, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 code_info__set_resume_point_and_frame_to_unknown -->
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(ResumePoints, _, _, Allow) },
+	{ FailInfo0 = fail_info(ResumePoints, _, _, CondEnv, Allow) },
 	{ FailInfo = fail_info(ResumePoints, resume_point_unknown,
-		may_be_different, Allow) },
+		may_be_different, CondEnv, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
 
 code_info__generate_failure(Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -1889,7 +1917,7 @@
 
 code_info__fail_if_rval_is_false(Rval0, Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -1943,13 +1971,13 @@
 
 code_info__failure_is_direct_branch(CodeAddr) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, resume_point_known, _, _) },
+	{ FailInfo = fail_info(ResumePoints, resume_point_known, _, _, _) },
 	{ stack__top(ResumePoints, TopResumePoint) },
 	code_info__pick_matching_resume_addr(TopResumePoint, CodeAddr).
 
 code_info__may_use_nondet_tailcall(MayTailCall) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _, _, _) },
 	(
 		{ ResumeKnown = resume_point_known },
 		{ stack__top_det(ResumePoints, TopResumePoint) },
@@ -2069,7 +2097,7 @@
 
 code_info__flush_resume_vars_to_stack(Code) -->
 	code_info__get_fail_info(FailInfo),
-	{ FailInfo = fail_info(ResumePointStack, _, _, _) },
+	{ FailInfo = fail_info(ResumePointStack, _, _, _, _) },
 	{ stack__top_det(ResumePointStack, ResumePoint) },
 	{ code_info__pick_stack_resume_point(ResumePoint, StackMap, _) },
 	{ map__to_assoc_list(StackMap, StackLocs) },
@@ -2119,8 +2147,9 @@
 	{ stack__init(ResumeStack0) },
 	{ stack__push(ResumeStack0, ResumePoint, ResumeStack) },
 	code_info__get_fail_info(FailInfo0),
-	{ FailInfo0 = fail_info(_, _, _, Allow) },
-	{ FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr, Allow) },
+	{ FailInfo0 = fail_info(_, _, _, _, Allow) },
+	{ FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr,
+		not_inside_non_condition, Allow) },
 	code_info__set_fail_info(FailInfo).
 
 %---------------------------------------------------------------------------%
cvs diff: Diffing compiler/notes
Index: compiler/notes/failure.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/failure.html,v
retrieving revision 1.4
diff -u -u -r1.4 failure.html
--- failure.html	1998/07/29 08:54:48	1.4
+++ failure.html	1998/08/05 08:46:49
@@ -135,6 +135,9 @@
 
 The proposed code generator uses two data structures for managing failure:
 the resume point stack and the left context.
+It also consults the option --allow-hijacks
+that says whether hijacks (see below) of nondet stack frames are allowed.
+Grades that call for accurate garbage collection imply --no-allow-hijacks.
 
 <h3> The resume point stack </h3>
 
@@ -217,21 +220,20 @@
 	</ul>
 
 <li>
-The hijacks_allowed subfield can take on
-one of the two values allowed and not_allowed,
-saying whether the code generator is allowed to hijack
-the redoip and redofr slots of the top nondet stack frame.
+The condition_environment subfield can take on
+one of the two values inside_non_condition and not_inside_non_condition,
+saying whether we are inside a model_non goal
+that is the condition of an if-then-else.
 </ul>
 
 <p>
 
 The resume_point_known subfield is initialized to known in all procedures.
-curfr_maxfr is initialized to must_be_equal in model_non procedures,
+The curfr_maxfr subfield is initialized to
+must_be_equal in model_non procedures,
 and to may_be_different in other procedures.
-The hijacks_allowed subfield is initialized to not_allowed
-if the compiler is given the --no-allow-hijacks compiler option,
-and to allowed otherwise.
-Grades that call for accurate garbage collection imply --no-allow-hijacks.
+The condition_environment subfield
+is always initialized to not_inside_non_condition.
 
 <p>
 
@@ -314,18 +316,27 @@
 </ul>
 
 <h3> Classifying left contexts </h3>
+
+The code generator classifies left contexts
+into those in which hijacking is allowed,
+and those in which hijacking is not allowed.
+Hijacking is allowed only if the --allow-hijacks option is set,
+and the condition_environment subfield is not_inside_non_condition.
+
+<p>
 
-In many cases, the code generator classifies left contexts into four cases:
+The code generator further classifies left contexts
+in which hijacking is allowed into the following three categories:
 
 <p>
 
 <ul>
-<li> no-hijack case: hijacks_allowed is not allowed
-<li> best case: hijacks_allowed is allowed,
+<li> best case:
 resume_point_known is known and curfr_maxfr is must_be_equal
-<li> middle case: hijacks_allowed is allowed,
+<li> middle case:
 resume_point_known is unknown and curfr_maxfr is must_be_equal
-<li> worst case: hijacks_allowed is allowed and curfr_maxfr is may_be_different
+<li> worst case:
+curfr_maxfr is may_be_different
 </ul>
 
 <p>
@@ -532,22 +543,54 @@
 will restore it to its original value before finally failing,
 that is too late in this case.)
 Therefore before entering the condition,
-the code generator sets the hijacks_allowed subfield to not_allowed; 
+the code generator sets condition_environment to inside_non_condition; 
 on exit from the condition, it restores the original value.
-(This is the only time the value of hijacks_allowed is ever changed,
-so if hijacks_allowed starts out as not_allowed,
-it will always stay not_allowed.)
+(These are the only times the value of condition_environment is ever changed.)
 
 <p>
 
 Before entering the condition, the code generator will set resume_point_known
-to yes, since the resumption point to go to on failure of the condition is
+to known, since the resumption point to go to on failure of the condition is
 known (it is the start of the else part). However, this resumption point
 does not apply to failures in the then part. Therefore before entering the
 then part, the code generator will reset resume_point_known to the value
 it had before entering the if-then-else, except if resume_point_known
 has become unknown during the generation of code for the condition, in which
 case it will continue to be unknown.
+
+<p>
+
+A failure inside the condition should cause
+a branch to the start of the else case
+only if the condition has not already succeeded.
+In general, the code inside the condition
+may branch directly to the start of the else case
+only up to the first goal that can succeed more than once;
+any other goal following such a goal should branch through the redoip slot
+on which the if-then-else performs the soft cut.
+There are only two kinds of constructs that can succeed more than once:
+calls (including higher order and method calls) and disjunctions.
+When the code generator processes a call that can succeed more than once,
+it sets resume_point_known to unknown,
+which causes later failures to perform a redo.
+To ensure that code in the last disjunct of a model_non disjunction
+and code following a model_non disjunction also fail via a redo,
+the code generator will,
+on entering the last disjunct of a model_non disjunction,
+check whether condition_environment is inside_non_condition,
+and if yes, it will set resume_point_known to unknown.
+(We do not do this in disjuncts other than the last
+because non-last disjuncts fail to the start of the next disjunct).
+Since at the end of branched control structures such as disjunctions
+the code generator sets resume_point_known to unknown
+if resume_point_known was unknown at the end of any branch,
+this ensures that resume_point_known will stay unknown after the disjunction.
+(The end of branched control structures
+treat the curfr_vs_maxfr subfield similarly, i.e. set it to may_be_different
+if it was may_be_different at the end of any branch.
+The condition_environment subfield must, by construction,
+have the same value at the end of every branch,
+and this is the value it will have after the branched control structure.)
 
 <h3> Handling nondet if-then-elses with semi or det conditions </h3>
 
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/Togl-1.2
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/general
Index: tests/general/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/general/Mmakefile,v
retrieving revision 1.19
diff -u -u -r1.19 Mmakefile
--- Mmakefile	1998/07/29 08:56:24	1.19
+++ Mmakefile	1998/08/05 02:11:02
@@ -51,6 +51,7 @@
 		partition \
 		petdr1 \
 		prune_switch \
+		semi_fail_in_non_ite \
 		semidet_lambda \
 		semidet_map \
 		set_test \
Index: tests/general/complex_failure.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/complex_failure.m,v
retrieving revision 1.1
diff -u -u -r1.1 complex_failure.m
--- complex_failure.m	1998/07/29 08:56:29	1.1
+++ complex_failure.m	1998/08/05 02:08:41
@@ -3,11 +3,6 @@
 % by the disjunction's clobbering some of the same redoip/redofr slots used
 % for the soft cut in the if-then-else.
 
-% Note that NU-Prolog cannot execute this test case correctly. With -> ;
-% notation, NU-Prolog does a hard neck cut, which is not Mercury's desired
-% semantics; with the if-then-else notation, it delays the conditions
-% since they are not ground.
-
 :- module complex_failure.
 
 :- interface.
Index: tests/general/semi_fail_in_non_ite.exp
===================================================================
RCS file: semi_fail_in_non_ite.exp
diff -N semi_fail_in_non_ite.exp
--- /dev/null	Wed May 28 10:49:58 1997
+++ semi_fail_in_non_ite.exp	Wed Aug  5 12:10:23 1998
@@ -0,0 +1 @@
+[1600, 1601, 1800, 1801, 1900, 1901, 6600, 6601]
Index: tests/general/semi_fail_in_non_ite.m
===================================================================
RCS file: semi_fail_in_non_ite.m
diff -N semi_fail_in_non_ite.m
--- /dev/null	Wed May 28 10:49:58 1997
+++ semi_fail_in_non_ite.m	Wed Aug  5 12:06:00 1998
@@ -0,0 +1,126 @@
+% This test case exercises the code generator's handling of if-then-elses
+% whose conditions include nondet disjunctions, looking for problems caused
+% by the disjunction's clobbering some of the same redoip/redofr slots used
+% for the soft cut in the if-then-else.
+
+:- module semi_fail_in_non_ite.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list, int.
+
+main -->
+	{ solutions(p1, Xs1) },
+	print_list(Xs1).
+
+:- pred p1(int::out) is nondet.
+
+p1(X) :-
+	p(1, X).
+
+:- pred p2(int::out) is nondet.
+
+p2(X) :-
+	p(2, X).
+
+:- pred p3(int::out) is nondet.
+
+p3(X) :-
+	p(3, X).
+
+:- pred p(int::in, int::out) is nondet.
+
+p(A, X) :-
+	% The first if-then-else can hijack the redoip/redofr slots
+	% of p's frame.
+	( if
+		some [B] ( q(A, B) ; r(A, B) )
+	then
+		C is B * 10
+		% s(B, C)
+	else
+		C is A * 10
+		% s(A, C)
+	),
+	% The second if-then-else cannot hijack the redoip/redofr slots
+	% of p's frame, since this may not be (and usually won't be)
+	% on top when execution gets here.
+	( if
+		some [D] (
+			q(C, D)
+		;
+			C = 260,
+			D = 690
+		)
+	then
+		s(D, X)
+	else
+		s(C, X)
+	).
+
+:- pred q(int::in, int::out) is nondet.
+
+q(1, 15).
+q(1, 16).
+q(2, 25).
+q(2, 26).
+q(3, 35).
+
+q(150, 660).
+q(161, 661).
+q(281, 662).
+
+:- pred r(int::in, int::out) is nondet.
+
+r(1, 18).
+r(1, 19).
+r(2, 28).
+r(2, 29).
+r(3, 38).
+r(260, 690).
+r(370, 698).
+
+:- pred s(int::in, int::out) is nondet.
+
+s(F, G) :-
+	F < 695,
+	(
+		G is 10 * F
+	;
+		G is 10 * F + 1
+	).
+
+:- pred print_list(list(int), io__state, io__state).
+:- mode print_list(in, di, uo) is det.
+
+print_list(Xs) -->
+	(
+		{ Xs = [] }
+	->
+		io__write_string("[]\n")
+	;
+		io__write_string("["),
+		print_list_2(Xs),
+		io__write_string("]\n")
+	).
+
+:- pred print_list_2(list(int), io__state, io__state).
+:- mode print_list_2(in, di, uo) is det.
+
+print_list_2([]) --> [].
+print_list_2([X|Xs]) --> 
+	io__write_int(X),
+	(
+		{ Xs = [] }
+	->
+		[]
+	;
+		io__write_string(", "),
+		print_list_2(Xs)
+	).
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list