[m-rev.] for review: minimal model tabling enhancements

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Mar 14 16:58:32 AEDT 2003


Since miminal model debugging is currently not operational, only the parts
of this diff that outside #ifdef MR_USE_MINIMAL_MODEL really need to be
reviewed.

Zoltan.

This change adds new facilities for debugging minimal model tabling, and
has several bug fixes found with the aid of those facilities. Most of the
diff affects the behavior of the system only in minimal model grades and/or
when debugging flags are defined.

compiler/ite_gen.m:
	In minimal model grades, surround the conditions of if-then-elses
	with calls to three functions. These functions detect when a
	condition fails due to one or more suspensions, and abort the
	program. (After resumptions, the condition may actually have
	solutions, but by then the computation has committed to the wrong
	path.)

compiler/table_gen.m:
	Change the program transformation for model_non predicates
	to use a switch instead of nested if-then-elses, to avoid the
	overhead of wrapping the condition. The version with switches
	is also a bit easier to debug.

	The transformation for model_det and model_semi predicates
	stays as before, because for such predicates finding the status
	(which we want to switch on) requires computation, not just a lookup.

	Switch to state variable syntax in the affacted predicates.

	Make the error message for an internal error in loopcheck predicates
	more precise.

	Mark the code fragments that modify tabling data structures as impure
	and code fragments that examine tabling data structures as semipure.

runtime/mercury_stacks.[ch]:
	Implement the new stack of possibly negated contexts that we use
	to detect false failures due to suspensions in negated contexts.

	Fix a bug: don't refer to MR_cut_stack[-1].

	Shorten the name of the generator stack.

runtime/mercury_context.[ch]:
runtime/mercury_memory.c:
runtime/mercury_wrapper.[ch]:
	Allocate memory for the new stack of possibly negated contexts.

	Use the shortened name of the generator stack.

runtime/mercury_regorder.h:
	Allocate a pointer for the new stack of possibly negated contexts.

runtime/mercury_minimal_model.[ch]:
	A new module holding the part of mercury_tabling.[ch]
	that is specific to minimal model tabling. This version contains
	tools to help debugging of minimal model tabling, as well as some
	bug fixes found with the aid of those tools.

runtime/mercury_tabling.[ch]:
	Remove the code moved to mercury_minimal_model.[ch], and add the
	code moved here from trace/mercury_trace_internal.c.

	Add prefixes to a bunch of structure fields to make it easier
	to read code accessing those fields.

	Add mechanisms to allocate and copy tabling structures with type
	safety.

runtime/mercury_imp.h:
	#include the new header file, if it is needed.

runtime/Mmakefile:
	Mention the new module, and fix sortedness errors.

runtime/mercury_stack_trace.c:
	Fix a bug that sometimes caused stack traces to abort in minimal model
	grades: they were trying to get layout information from labels
	that do not have them, such as do_fail.

	If MR_TABLE_DEBUG is defined, print the locations of stack frames
	when doing stack dumps.

runtime/mercury_trace_base.h:
	Export to mercury_stack_trace.c the labels that we use to let the
	debugger get control at redos and fails, since they don't have
	layout information.

runtime/mercury_types.h:
	Move typedefs here from mercury_tabling.h, and add typedefs for some
	newly added types.

runtime/mercury_engine.[ch]:
	Add a table mapping debugging flags to their offsets in the
	MR_debugflag array, for use in the debugger.

runtime/mercury_misc.c:
	Make the formatting of det stack pointers the same as nondet stack
	pointers in debugging output.

library/table_builtin.m:
	Conform to the new names of some fields.

	Add a predicate to return the status of a subgoal.

	Add conditionally compiled debugging code.

trace/mercury_trace.c:
	Conform to the new names of some fields.

trace/mercury_trace_internal.c:
	Add two new mdb commands, to print the cut stack and the new possibly
	negated context stack.

	Add two new mdb commands to print a subgoal and a consumer.

	Move some of the code to print tabling-related
	data structures to runtime/mercury_tabling.[ch].

	Add a new mdb command to report the values of debugging flags and
	to set and clear them. Previously, one had to turn on these debugging
	flags with environment variables, which were problematic because they
	turned on diagnostic printouts even in Mercury programs that *weren't*
	being debugged, such as the Mercury compiler when being used to
	generate the program to be debugged. Now the flags can be turned on
	from a .mdbrc file, which eliminates much setting and unsetting of
	environment variables.

doc/user_guide.tex:
	Document the new mdb commands.

tests/debugger/mdb_command_test.inp:
	Test the documentation of the new mdb commands.

tests/debugger/completion.exp:
	Expect the new commands in the command completion test.

tests/debugger/all_solutions.exp3:
tests/debugger/exception_value.exp3:
tests/debugger/declarative/catch.exp3:
tests/debugger/declarative/ho5.exp3:
tests/debugger/declarative/throw.exp3:
	New expected test cases for use in minimal model grades. They
	differ from existing expected output files only in the precise
	phrasing of error messages.

tests/tabling/Mmakefile:
	Enable the mday test case, now that we pass it.

cvs diff: Diffing .
cvs diff: Diffing analysis
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/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/ite_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ite_gen.m,v
retrieving revision 1.68
diff -u -b -r1.68 ite_gen.m
--- compiler/ite_gen.m	9 Sep 2002 07:48:13 -0000	1.68
+++ compiler/ite_gen.m	19 Nov 2002 06:58:34 -0000
@@ -40,7 +40,7 @@
 :- import_module backend_libs__builtin_ops.
 :- import_module libs__options, libs__globals, libs__tree.
 
-:- import_module bool, set, term, list, map, std_util, require.
+:- import_module bool, string, set, term, list, map, std_util, require.
 
 ite_gen__generate_ite(CodeModel, CondGoal0, ThenGoal, ElseGoal, IteGoalInfo,
 		Code) -->
@@ -177,6 +177,8 @@
 		label(EndLabel)
 			- "end of if-then-else"
 	]) },
+	{ make_pneg_context_wrappers(Globals, PNegCondCode, PNegThenCode,
+		PNegElseCode) },
 	{ Code =
 		tree(FlushCode,
 		tree(SaveHpCode,
@@ -184,10 +186,12 @@
 		tree(PrepareHijackCode,
 		tree(EffectResumeCode,
 		tree(CondTraceCode,
+		tree(PNegCondCode,
 		tree(CondCode,
 		tree(ThenNeckCode,
 		tree(ResetTicketCode,
 		tree(ThenTraceCode,
+		tree(PNegThenCode,
 		tree(ThenCode,
 		tree(ThenSaveCode,
 		tree(JumpToEndCode,
@@ -196,9 +200,10 @@
 		tree(RestoreHpCode,
 		tree(RestoreTicketCode,
 		tree(ElseTraceCode,
+		tree(PNegElseCode,
 		tree(ElseCode,
 		tree(ElseSaveCode,
-		     EndLabelCode))))))))))))))))))))
+		     EndLabelCode)))))))))))))))))))))))
 	},
 	code_info__after_all_branches(StoreMap, MaybeEnd).
 
@@ -349,6 +354,8 @@
 	trace__maybe_generate_negated_event_code(Goal, NotGoalInfo,
 		neg_success, SuccessTraceCode),
 
+	{ make_pneg_context_wrappers(Globals, PNegCondCode, PNegThenCode,
+		PNegElseCode) },
 	{ Code =
 		tree(FlushCode,
 		tree(PrepareHijackCode,
@@ -356,16 +363,86 @@
 		tree(SaveHpCode,
 		tree(SaveTicketCode,
 		tree(EnterTraceCode,
+		tree(PNegCondCode,
 		tree(GoalCode,
 		tree(ThenNeckCode,
 		tree(PruneTicketCode,
 		tree(FailTraceCode,
+		tree(PNegThenCode,
 		tree(FailCode,
 		tree(ResumeCode,
 		tree(ElseNeckCode,
 		tree(RestoreTicketCode,
 		tree(RestoreHpCode,
-		     SuccessTraceCode)))))))))))))))
+		tree(SuccessTraceCode,
+		     PNegElseCode))))))))))))))))))
 	}.
+
+%---------------------------------------------------------------------------%
+
+	% If the code in the condition depends on a consumer
+	% of a generator that is not complete by the time we finish
+	% executing the condition, then failure out of the condition
+	% does not necessarily mean that the condition has no solution;
+	% it may mean simply that the condition's solution depends on
+	% a generator solution that hasn't been produced yet and thus
+	% hasn't been given to the consumer yet.
+	%
+	% Detecting such situations requires knowing whether tabled
+	% subgoals (both generators and consumers) are started inside
+	% possibly negated contexts or not, which is why we wrap the
+	% condition inside MR_pneg_enter_{cond,then,exit}.
+
+:- pred make_pneg_context_wrappers(globals::in, code_tree::out, code_tree::out,
+	code_tree::out) is det.
+
+make_pneg_context_wrappers(Globals, PNegCondCode, PNegThenCode, PNegElseCode)
+		:-
+	globals__lookup_bool_option(Globals, use_minimal_model,
+		UseMinimalModel),
+	(
+		UseMinimalModel = yes,
+
+		PNegCondComponents = [
+			pragma_c_raw_code(
+				wrap_transient("\t\tMR_pneg_enter_cond();\n"),
+				live_lvals_info(set__init))
+		],
+		PNegThenComponents = [
+			pragma_c_raw_code(
+				wrap_transient("\t\tMR_pneg_enter_then();\n"),
+				live_lvals_info(set__init))
+		],
+		PNegElseComponents = [
+			pragma_c_raw_code(
+				wrap_transient("\t\tMR_pneg_enter_else();\n"),
+				live_lvals_info(set__init))
+		],
+		PNegCondCode = node([
+			pragma_c([], PNegCondComponents, will_not_call_mercury,
+				no, no, no, no, no) - ""
+		]),
+		PNegThenCode = node([
+			pragma_c([], PNegThenComponents, will_not_call_mercury,
+				no, no, no, no, no) - ""
+		]),
+		PNegElseCode = node([
+			pragma_c([], PNegElseComponents, will_not_call_mercury,
+				no, no, no, no, no) - ""
+		])
+	;
+		UseMinimalModel = no,
+		PNegCondCode = empty,
+		PNegThenCode = empty,
+		PNegElseCode = empty
+	).
+
+:- func wrap_transient(string) = string.
+
+wrap_transient(Code) =
+	string__append_list([
+		"\t\tMR_save_transient_registers();\n",
+		Code,
+		"\t\tMR_restore_transient_registers();\n"]).
 
 %---------------------------------------------------------------------------%
Index: compiler/table_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/table_gen.m,v
retrieving revision 1.44
diff -u -b -r1.44 table_gen.m
--- compiler/table_gen.m	28 Feb 2003 00:21:38 -0000	1.44
+++ compiler/table_gen.m	3 Mar 2003 07:29:06 -0000
@@ -100,20 +100,20 @@
 %			% Look up the input arguments, and set up the table.
 %		impure table_lookup_insert_int(T0, A, T1),
 %		impure table_nondet_setup(T1, T2),
-%		(if
-%			semipure table_nondet_is_complete(T2)
-%		then
+%		impure table_subgoal_status(T2, Status),
+%		(
+%			Status = complete,
 %				% Return all the answers from the complete
 %				% table.
 %			impure table_nondet_return_all_ans(T2, Ans),
 %			impure table_restore_int_ans(Ans, 0, B)
-%		else if
-%			semipure table_nondet_is_active(T2)
-%		then
+%		;
+%			Status = active,
 %				% Suspend the current computational branch.
 %			impure table_nondet_suspend(T2, Ans),
 %			impure table_restore_int_ans(Ans, 0, B)
-%		else
+%		;
+%			Status = inactive,
 %		   	(
 %					% Mark that this subgoal is being
 %					% evaluated.
@@ -713,7 +713,7 @@
 		instmap_delta_restrict(RestoreAnsInstMapDelta0,
 			RestoreAnsNonLocals, RestoreAnsInstMapDelta),
 		goal_info_init(RestoreAnsNonLocals, RestoreAnsInstMapDelta,
-			det, pure, Context, RestoreAnsGoalInfo0),
+			det, semipure, Context, RestoreAnsGoalInfo0),
 		goal_info_add_feature(RestoreAnsGoalInfo0, hide_debug_event,
 			RestoreAnsGoalInfo),
 		RestoreAnsGoal = RestoreAnsGoalEx - RestoreAnsGoalInfo
@@ -749,7 +749,7 @@
 	instmap_delta_restrict(CallSaveAnsInstMapDelta0,
 		CallSaveAnsNonLocals, CallSaveAnsInstMapDelta),
 	goal_info_init(CallSaveAnsNonLocals, CallSaveAnsInstMapDelta, det,
-		pure, Context, CallSaveAnsGoalInfo0),
+		impure, Context, CallSaveAnsGoalInfo0),
 	goal_info_add_feature(CallSaveAnsGoalInfo0, hide_debug_event,
 		CallSaveAnsGoalInfo),
 	CallSaveAnsGoal = CallSaveAnsGoalEx - CallSaveAnsGoalInfo,
@@ -761,7 +761,7 @@
 	set__insert(OrigNonLocals, TableVar, GenIfNecNonLocals),
 	instmap_delta_restrict(GenIfNecInstMapDelta0, GenIfNecNonLocals,
 		GenIfNecInstMapDelta),
-	goal_info_init(GenIfNecNonLocals, GenIfNecInstMapDelta, det, pure,
+	goal_info_init(GenIfNecNonLocals, GenIfNecInstMapDelta, det, impure,
 		Context, GenIfNecGoalInfo0),
 	goal_info_add_feature(GenIfNecGoalInfo0, hide_debug_event,
 		GenIfNecGoalInfo),
@@ -775,7 +775,7 @@
 	instmap_delta_restrict(CheckAndGenAnsInstMapDelta0,
 		CheckAndGenAnsNonLocals, CheckAndGenAnsInstMapDelta),
 	goal_info_init(CheckAndGenAnsNonLocals, CheckAndGenAnsInstMapDelta,
-		det, pure, Context, CheckAndGenAnsGoalInfo0),
+		det, impure, Context, CheckAndGenAnsGoalInfo0),
 	goal_info_add_feature(CheckAndGenAnsGoalInfo0, hide_debug_event,
 		CheckAndGenAnsGoalInfo),
 	CheckAndGenAnsGoal = CheckAndGenAnsGoalEx - CheckAndGenAnsGoalInfo,
@@ -786,7 +786,7 @@
 		BodyInstMapDelta0),
 	instmap_delta_restrict(BodyInstMapDelta0, OrigNonLocals,
 		BodyInstMapDelta),
-	goal_info_init(OrigNonLocals, BodyInstMapDelta, det, pure,
+	goal_info_init(OrigNonLocals, BodyInstMapDelta, det, impure,
 		Context, BodyGoalInfo0),
 	goal_info_add_feature(BodyGoalInfo0, hide_debug_event, BodyGoalInfo),
 	Goal = BodyGoalEx - BodyGoalInfo.
@@ -801,8 +801,8 @@
 	prog_var::out, hlds_goal::out, proc_table_info::out) is det.
 
 table_gen__create_new_det_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
-		HeadVars, HeadVarModes, VarTypes0, VarTypes, VarSet0, VarSet,
-		TableInfo0, TableInfo, TableVar, Goal, ProcTableInfo) :-
+		HeadVars, HeadVarModes, !VarTypes, !VarSet, !TableInfo,
+		TableVar, Goal, ProcTableInfo) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -812,28 +812,25 @@
 	goal_info_get_instmap_delta(OrigGoalInfo, OrigInstMapDelta),
 	goal_info_get_context(OrigGoalInfo, Context),
 
-	ModuleInfo = TableInfo0 ^ table_module_info,
+	ModuleInfo = !.TableInfo ^ table_module_info,
 
 	get_input_output_vars(HeadVars, HeadVarModes, ModuleInfo, InputVars,
 		OutputVars),
 
 	generate_simple_lookup_goal(InputVars, PredId, ProcId, Context,
-		VarTypes0, VarTypes1, VarSet0, VarSet1, TableInfo0, TableInfo1,
-		TableVar, LookUpGoal, Steps),
+		!VarTypes, !VarSet, !TableInfo, TableVar, LookUpGoal, Steps),
 	generate_call("table_simple_is_complete", [TableVar], semidet,
 		yes(semipure), [], ModuleInfo, Context, CompleteCheckGoal),
 	allocate_slot_numbers(OutputVars, 0, NumberedOutputVars),
 	list__length(NumberedOutputVars, BlockSize),
 	generate_save_goal(NumberedOutputVars, TableVar, BlockSize,
-		Context, VarTypes1, VarTypes2, VarSet1, VarSet2,
-		TableInfo1, TableInfo, SaveAnsGoal0),
+		Context, !VarTypes, !VarSet, !TableInfo, SaveAnsGoal0),
 	generate_restore_goal(NumberedOutputVars, TableVar,
-		ModuleInfo, Context, VarTypes2, VarTypes3, VarSet2, VarSet3,
-		RestoreAnsGoal0),
+		ModuleInfo, Context, !VarTypes, !VarSet, RestoreAnsGoal0),
 	generate_call("table_simple_mark_as_inactive", [TableVar], det,
 		yes(impure), [], ModuleInfo, Context, MarkAsInactiveGoal),
-	generate_loop_error_goal(TableInfo, Context, VarTypes3, VarTypes,
-		VarSet3, VarSet, LoopErrorGoal),
+	generate_loop_error_goal(!.TableInfo, Context, infinite_recursion_msg,
+		!VarTypes, !VarSet, LoopErrorGoal),
 	( Detism = erroneous ->
 		% In this case, the RestoreAnsGoal will never be reached,
 		% but to ensure that the generated code is determinism-correct,
@@ -866,7 +863,7 @@
 		NoLoopGenInstMapDelta0),
 	instmap_delta_restrict(NoLoopGenInstMapDelta0, GenAnsNonLocals,
 		NoLoopGenInstMapDelta),
-	goal_info_init(GenAnsNonLocals, NoLoopGenInstMapDelta, det, pure,
+	goal_info_init(GenAnsNonLocals, NoLoopGenInstMapDelta, det, impure,
 		Context, NoLoopGenGoalInfo0),
 	goal_info_add_feature(NoLoopGenGoalInfo0, hide_debug_event,
 		NoLoopGenGoalInfo),
@@ -878,7 +875,7 @@
 		NoLoopGenAnsGoal], GenAnsInstMapDelta0),
 	instmap_delta_restrict(GenAnsInstMapDelta0, GenAnsNonLocals,
 		GenAnsInstMapDelta),
-	goal_info_init(GenAnsNonLocals, GenAnsInstMapDelta, det, pure,
+	goal_info_init(GenAnsNonLocals, GenAnsInstMapDelta, det, impure,
 		Context, GenAnsGoalInfo0),
 	goal_info_add_feature(GenAnsGoalInfo0, hide_debug_event,
 		GenAnsGoalInfo),
@@ -890,17 +887,17 @@
 		ITEInstMapDelta0),
 	instmap_delta_restrict(ITEInstMapDelta0, GenAnsNonLocals,
 		ITEInstMapDelta),
-	goal_info_init(GenAnsNonLocals, ITEInstMapDelta, det, pure,
+	goal_info_init(GenAnsNonLocals, ITEInstMapDelta, det, impure,
 		Context, ITEGoalInfo0),
 	goal_info_add_feature(ITEGoalInfo0, hide_debug_event, ITEGoalInfo),
 	ITEGoal = ITEGoalEx - ITEGoalInfo,
 
 	GoalEx = conj([LookUpGoal, ITEGoal]),
-	goal_info_init(OrigNonLocals, OrigInstMapDelta, det, pure,
+	goal_info_init(OrigNonLocals, OrigInstMapDelta, det, impure,
 		Context, GoalInfo0),
 	goal_info_add_feature(GoalInfo0, hide_debug_event, GoalInfo),
 	Goal = GoalEx - GoalInfo,
-	generate_gen_proc_table_info(TableInfo, Steps, InputVars, OutputVars,
+	generate_gen_proc_table_info(!.TableInfo, Steps, InputVars, OutputVars,
 		ProcTableInfo).
 
 %-----------------------------------------------------------------------------%
@@ -915,8 +912,8 @@
 	prog_var::out, hlds_goal::out, proc_table_info::out) is det.
 
 table_gen__create_new_semi_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
-		HeadVars, HeadVarModes, VarTypes0, VarTypes, VarSet0, VarSet,
-		TableInfo0, TableInfo, TableVar, Goal, ProcTableInfo) :-
+		HeadVars, HeadVarModes, !VarTypes, !VarSet, !TableInfo,
+		TableVar, Goal, ProcTableInfo) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -926,25 +923,22 @@
 	goal_info_get_instmap_delta(OrigGoalInfo, OrigInstMapDelta),
 	goal_info_get_context(OrigGoalInfo, Context),
 
-	ModuleInfo = TableInfo0 ^ table_module_info,
+	ModuleInfo = !.TableInfo ^ table_module_info,
 	get_input_output_vars(HeadVars, HeadVarModes, ModuleInfo, InputVars,
 		OutputVars),
 
 	generate_simple_lookup_goal(InputVars, PredId, ProcId, Context,
-		VarTypes0, VarTypes1, VarSet0, VarSet1, TableInfo0, TableInfo1,
-		TableVar, LookUpGoal, Steps),
+		!VarTypes, !VarSet, !TableInfo, TableVar, LookUpGoal, Steps),
 	generate_call("table_simple_is_complete", [TableVar], semidet,
 		yes(semipure), [], ModuleInfo, Context, CompleteCheckGoal),
 	allocate_slot_numbers(OutputVars, 0, NumberedOutputVars),
 	list__length(NumberedOutputVars, BlockSize),
 	generate_save_goal(NumberedOutputVars, TableVar, BlockSize,
-		Context, VarTypes1, VarTypes2, VarSet1, VarSet2,
-		TableInfo1, TableInfo, SaveAnsGoal0),
+		Context, !VarTypes, !VarSet, !TableInfo, SaveAnsGoal0),
 	generate_restore_goal(NumberedOutputVars, TableVar,
-		ModuleInfo, Context, VarTypes2, VarTypes3, VarSet2, VarSet3,
-		RestoreTrueAnsGoal),
-	generate_loop_error_goal(TableInfo, Context,
-		VarTypes3, VarTypes, VarSet3, VarSet, LoopErrorGoal),
+		ModuleInfo, Context, !VarTypes, !VarSet, RestoreTrueAnsGoal),
+	generate_loop_error_goal(!.TableInfo, Context, infinite_recursion_msg,
+		!VarTypes, !VarSet, LoopErrorGoal),
 	generate_call("table_simple_mark_as_failed", [TableVar],
 		det, yes(impure), [], ModuleInfo, Context, MarkAsFailedGoal0),
 	append_fail(MarkAsFailedGoal0, MarkAsFailedGoal),
@@ -980,7 +974,7 @@
 		instmap_delta_restrict(NoLoopGenInstMapDelta0, GenAnsNonLocals,
 			NoLoopGenInstMapDelta),
 		goal_info_init(GenAnsNonLocals, NoLoopGenInstMapDelta, semidet,
-			pure, Context, NoLoopGenGoalInfo0),
+			impure, Context, NoLoopGenGoalInfo0),
 		goal_info_add_feature(NoLoopGenGoalInfo0, hide_debug_event,
 			NoLoopGenGoalInfo),
 		NoLoopGenAnsGoal = NoLoopGenAnsGoalEx - NoLoopGenGoalInfo,
@@ -992,7 +986,7 @@
 		instmap_delta_restrict(GenTrueAnsInstMapDelta0,
 			GenAnsNonLocals, GenTrueAnsInstMapDelta),
 		goal_info_init(GenAnsNonLocals, GenTrueAnsInstMapDelta,
-			semidet, pure, Context, GenTrueAnsGoalInfo0),
+			semidet, impure, Context, GenTrueAnsGoalInfo0),
 		goal_info_add_feature(GenTrueAnsGoalInfo0, hide_debug_event,
 			GenTrueAnsGoalInfo),
 		GenTrueAnsGoal = GenTrueAnsGoalEx - GenTrueAnsGoalInfo
@@ -1017,7 +1011,7 @@
 		instmap_delta_restrict(GenTrueAnsInstMapDelta0,
 			GenAnsNonLocals, GenTrueAnsInstMapDelta),
 		goal_info_init(GenAnsNonLocals, GenTrueAnsInstMapDelta,
-			semidet, pure, Context, GenTrueAnsGoalInfo0),
+			semidet, impure, Context, GenTrueAnsGoalInfo0),
 		goal_info_add_feature(GenTrueAnsGoalInfo0, hide_debug_event,
 			GenTrueAnsGoalInfo),
 		GenTrueAnsGoal = GenTrueAnsGoalEx - GenTrueAnsGoalInfo
@@ -1049,7 +1043,7 @@
 		instmap_delta_restrict(RestInstMapDelta0, RestNonLocals,
 			RestInstMapDelta),
 		goal_info_init(RestNonLocals, RestInstMapDelta, semidet,
-			pure, Context, RestAnsGoalInfo0),
+			semipure, Context, RestAnsGoalInfo0),
 		goal_info_add_feature(RestAnsGoalInfo0, hide_debug_event,
 			RestAnsGoalInfo),
 		RestoreAnsGoal = RestAnsGoalEx - RestAnsGoalInfo
@@ -1061,8 +1055,8 @@
 		GenAnsGoalInstMapDelta0),
 	instmap_delta_restrict(GenAnsGoalInstMapDelta0, GenAnsNonLocals,
 		GenAnsGoalInstMapDelta),
-	goal_info_init(GenAnsNonLocals, GenAnsGoalInstMapDelta, semidet, pure,
-		Context, GenAnsGoalInfo0),
+	goal_info_init(GenAnsNonLocals, GenAnsGoalInstMapDelta, semidet,
+		impure, Context, GenAnsGoalInfo0),
 	goal_info_add_feature(GenAnsGoalInfo0, hide_debug_event,
 		GenAnsGoalInfo),
 	GenAnsGoal = GenAnsGoalEx - GenAnsGoalInfo,
@@ -1073,17 +1067,17 @@
 		ITEInstMapDelta0),
 	instmap_delta_restrict(ITEInstMapDelta0, GenAnsNonLocals,
 		ITEInstMapDelta),
-	goal_info_init(GenAnsNonLocals, ITEInstMapDelta, semidet, pure,
+	goal_info_init(GenAnsNonLocals, ITEInstMapDelta, semidet, impure,
 		Context, ITEGoalInfo0),
 	goal_info_add_feature(ITEGoalInfo0, hide_debug_event, ITEGoalInfo),
 	ITEGoal = ITEGoalEx - ITEGoalInfo,
 
 	GoalEx = conj([LookUpGoal, ITEGoal]),
-	goal_info_init(OrigNonLocals, OrigInstMapDelta, semidet, pure,
+	goal_info_init(OrigNonLocals, OrigInstMapDelta, semidet, impure,
 		Context, GoalInfo0),
 	goal_info_add_feature(GoalInfo0, hide_debug_event, GoalInfo),
 	Goal = GoalEx - GoalInfo,
-	generate_gen_proc_table_info(TableInfo, Steps, InputVars, OutputVars,
+	generate_gen_proc_table_info(!.TableInfo, Steps, InputVars, OutputVars,
 		ProcTableInfo).
 
 %-----------------------------------------------------------------------------%
@@ -1098,8 +1092,8 @@
 	prog_var::out, hlds_goal::out, proc_table_info::out) is det.
 
 table_gen__create_new_non_goal(EvalMethod, Detism, OrigGoal, PredId, ProcId,
-		HeadVars, HeadVarModes, VarTypes0, VarTypes, VarSet0, VarSet,
-		TableInfo0, TableInfo, TableVar, Goal, ProcTableInfo) :-
+		HeadVars, HeadVarModes, !VarTypes, !VarSet, !TableInfo,
+		TableVar, Goal, ProcTableInfo) :-
 	% even if the original goal doesn't use all of the headvars,
 	% the code generated by the tabling transformation does,
 	% so we need to compute the nonlocals from the headvars rather
@@ -1109,95 +1103,95 @@
 	goal_info_get_instmap_delta(OrigGoalInfo, OrigInstMapDelta),
 	goal_info_get_context(OrigGoalInfo, Context),
 
-	ModuleInfo = TableInfo0 ^ table_module_info,
+	ModuleInfo = !.TableInfo ^ table_module_info,
 	get_input_output_vars(HeadVars, HeadVarModes, ModuleInfo, InputVars,
 		OutputVars),
 	allocate_slot_numbers(OutputVars, 0, NumberedOutputVars),
 	list__length(NumberedOutputVars, BlockSize),
 
 	generate_non_lookup_goal(InputVars, PredId, ProcId, Context,
-		VarTypes0, VarTypes1, VarSet0, VarSet1, TableInfo0, TableInfo1,
-		TableVar, LookUpGoal, Steps),
-	generate_call("table_nondet_is_complete", [TableVar], semidet,
-		yes(semipure), [], ModuleInfo, Context, CompleteCheckGoal),
+		!VarTypes, !VarSet, !TableInfo, TableVar, LookUpGoal, Steps),
+
+	generate_new_table_var("Status", status_type, !VarTypes, !VarSet,
+		StatusVar),
+
+	generate_call("table_subgoal_status", [TableVar, StatusVar], det,
+		yes(semipure), [StatusVar - ground(unique, none)],
+		ModuleInfo, Context, StatusGoal),
 	generate_non_save_goal(NumberedOutputVars, TableVar, BlockSize, Context,
-		VarTypes1, VarTypes2, VarSet1, VarSet2, TableInfo1, TableInfo,
-		SaveAnsGoal0),
+		!VarTypes, !VarSet, !TableInfo, SaveAnsGoal),
 	generate_restore_all_goal(Detism, NumberedOutputVars, TableVar,
-		ModuleInfo, Context, VarTypes2, VarTypes3, VarSet2, VarSet3,
-		RestoreAllAnsGoal),
-	generate_call("table_nondet_is_active", [TableVar], semidet,
-		yes(semipure), [], ModuleInfo, Context, IsActiveCheckGoal),
-	generate_suspend_goal(NumberedOutputVars, TableVar,
-		ModuleInfo, Context, VarTypes3, VarTypes4, VarSet3, VarSet4,
-		SuspendGoal),
-	generate_loop_error_goal(TableInfo, Context, VarTypes4, VarTypes,
-		VarSet4, VarSet, LoopErrorGoal),
+		ModuleInfo, Context, !VarTypes, !VarSet, RestoreAllAnsGoal),
+	generate_loop_error_goal(!.TableInfo, Context, infinite_recursion_msg,
+		!VarTypes, !VarSet, LoopErrorGoal),
 	generate_call("table_nondet_mark_as_active", [TableVar], det,
 		yes(impure), [], ModuleInfo, Context, MarkAsActiveGoal),
-	generate_call("table_nondet_resume", [TableVar], det, yes(impure),
-		[], ModuleInfo, Context, ResumeGoal0),
-	append_fail(ResumeGoal0, ResumeGoal1),
 
 	true_goal(TrueGoal),
-	fail_goal(FailGoal),
 
-	( EvalMethod = eval_memo ->
-		SaveAnsGoal = SaveAnsGoal0,
-		ActiveGoal = LoopErrorGoal
-	; EvalMethod = eval_loop_check ->
-		SaveAnsGoal = TrueGoal,
-		ActiveGoal = LoopErrorGoal
-	; EvalMethod = eval_minimal ->
-		SaveAnsGoal = SaveAnsGoal0,
-		ActiveGoal = SuspendGoal
+	(
+		EvalMethod = eval_memo,
+		AfterOrigGoal = SaveAnsGoal,
+		ActiveGoal = LoopErrorGoal,
+		CompleteGoal = RestoreAllAnsGoal
+	;
+		EvalMethod = eval_loop_check,
+		generate_loop_error_goal(!.TableInfo, Context,
+			"detected internal error", !VarTypes, !VarSet,
+			LoopInternalErrorGoal),
+		AfterOrigGoal = TrueGoal,
+		ActiveGoal = LoopErrorGoal,
+		CompleteGoal = LoopInternalErrorGoal
 	;
-		error(
-		"table_gen__create_new_non_goal: unsupported evaluation model")
+		EvalMethod = eval_minimal,
+		generate_suspend_goal(NumberedOutputVars, TableVar,
+			ModuleInfo, Context, !VarTypes, !VarSet, SuspendGoal),
+		AfterOrigGoal = SaveAnsGoal,
+		ActiveGoal = SuspendGoal,
+		CompleteGoal = RestoreAllAnsGoal
+	;
+		EvalMethod = eval_table_io(_, _),
+		error("table_gen__create_new_non_goal: table_io")
+	;
+		EvalMethod = eval_normal,
+		error("table_gen__create_new_non_goal: normal")
 	),
 
-	GenAnsGoalPart1Ex = conj([MarkAsActiveGoal, OrigGoal, SaveAnsGoal]),
-	set__insert(OrigNonLocals, TableVar, GenAnsGoalPart1NonLocals),
+	MainEx = conj([MarkAsActiveGoal, OrigGoal, AfterOrigGoal]),
+	set__insert(OrigNonLocals, TableVar, MainNonLocals),
 	create_instmap_delta([MarkAsActiveGoal, OrigGoal, SaveAnsGoal],
-		GenAnsGoalPart1IMD0),
-	instmap_delta_restrict(GenAnsGoalPart1IMD0, GenAnsGoalPart1NonLocals,
-		GenAnsGoalPart1IMD),
-	goal_info_init(GenAnsGoalPart1NonLocals, GenAnsGoalPart1IMD, nondet,
-		pure, Context, GenAnsGoalPart1GoalInfo0),
-	goal_info_add_feature(GenAnsGoalPart1GoalInfo0, hide_debug_event,
-		GenAnsGoalPart1GoalInfo),
-	GenAnsGoalPart1 = GenAnsGoalPart1Ex - GenAnsGoalPart1GoalInfo,
+		MainIMD0),
+	instmap_delta_restrict(MainIMD0, MainNonLocals, MainIMD),
+	goal_info_init(MainNonLocals, MainIMD, nondet, impure, Context,
+		MainGoalInfo0),
+	goal_info_add_feature(MainGoalInfo0, hide_debug_event, MainGoalInfo),
+	MainGoal = MainEx - MainGoalInfo,
 
 	( EvalMethod = eval_minimal ->
-		ResumeGoal = ResumeGoal1
-	;
-		ResumeGoal = FailGoal
-	),
-	GenAnsGoalEx = disj([GenAnsGoalPart1, ResumeGoal]),
-	GenAnsGoal = GenAnsGoalEx - GenAnsGoalPart1GoalInfo,
-
-	ITE1GoalEx = if_then_else([], IsActiveCheckGoal, ActiveGoal,
-		GenAnsGoal),
-	goal_info_add_feature(GenAnsGoalPart1GoalInfo, hide_debug_event,
-		ITE1GoalInfo),
-	ITE1Goal = ITE1GoalEx - ITE1GoalInfo,
-
-	( EvalMethod = eval_loop_check ->
-		ITE2Goal = ITE1Goal
-	;
-		ITE2GoalEx = if_then_else([], CompleteCheckGoal,
-			RestoreAllAnsGoal, ITE1Goal),
-		goal_info_add_feature(GenAnsGoalPart1GoalInfo,
-			hide_debug_event, ITE2GoalInfo),
-		ITE2Goal = ITE2GoalEx - ITE2GoalInfo
-	),
+		generate_call("table_nondet_resume", [TableVar], det,
+			yes(impure), [], ModuleInfo, Context, ResumeGoal0),
+		append_fail(ResumeGoal0, ResumeGoal),
+		InactiveEx = disj([MainGoal, ResumeGoal]),
+		InactiveGoal = InactiveEx - MainGoalInfo
+	;
+		InactiveGoal = MainGoal
+	),
+
+	mercury_table_builtin_module(TB),
+	SwitchArms = [
+		case(cons(qualified(TB, "inactive"), 0), InactiveGoal),
+		case(cons(qualified(TB, "complete"), 0), CompleteGoal),
+		case(cons(qualified(TB, "active"), 0), ActiveGoal)],
+	SwitchEx = switch(StatusVar, cannot_fail, SwitchArms),
+	goal_info_add_feature(MainGoalInfo, hide_debug_event, SwitchGoalInfo),
+	SwitchGoal = SwitchEx - SwitchGoalInfo,
 
-	GoalEx = conj([LookUpGoal, ITE2Goal]),
-	goal_info_init(OrigNonLocals, OrigInstMapDelta, nondet, pure,
+	GoalEx = conj([LookUpGoal, StatusGoal, SwitchGoal]),
+	goal_info_init(OrigNonLocals, OrigInstMapDelta, nondet, impure,
 		Context, GoalInfo0),
 	goal_info_add_feature(GoalInfo0, hide_debug_event, GoalInfo),
 	Goal = GoalEx - GoalInfo,
-	generate_gen_proc_table_info(TableInfo, Steps, InputVars, OutputVars,
+	generate_gen_proc_table_info(!.TableInfo, Steps, InputVars, OutputVars,
 		ProcTableInfo).
 
 %-----------------------------------------------------------------------------%
@@ -1262,7 +1256,8 @@
 	set__singleton_set(NonLocals0, TableVar),
 	set__insert_list(NonLocals0, Vars, NonLocals),
 	instmap_delta_from_assoc_list([], InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, det, pure, Context, GoalInfo0),
+	goal_info_init(NonLocals, InstMapDelta, det, impure, Context,
+		GoalInfo0),
 	goal_info_get_features(GoalInfo0, Features0),
 	set__insert(Features0, call_table_gen, Features),
 	goal_info_set_features(GoalInfo0, Features, GoalInfo),
@@ -1299,7 +1294,8 @@
 	set__insert_list(NonLocals0, Vars, NonLocals),
 	create_instmap_delta(Goals, InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, det, pure, Context, GoalInfo0),
+	goal_info_init(NonLocals, InstMapDelta, det, impure, Context,
+		GoalInfo0),
 	goal_info_get_features(GoalInfo0, Features0),
 	set__insert(Features0, call_table_gen, Features),
 	goal_info_set_features(GoalInfo0, Features, GoalInfo),
@@ -1371,7 +1367,7 @@
 			set__insert_list(NonLocals0, [TableVar, ArgVar],
 				NonLocals),
 			instmap_delta_from_assoc_list([], InstMapDelta),
-			goal_info_init(NonLocals, InstMapDelta, det, pure,
+			goal_info_init(NonLocals, InstMapDelta, det, impure,
 				Context, GoalInfo),
 			Goal = conj([RangeUnifyGoal, LookupGoal]) - GoalInfo,
 			Step = table_trie_step_enum(EnumRange),
@@ -1459,7 +1455,7 @@
 		create_instmap_delta([BlockSizeVarUnifyGoal, CreateAnsBlockGoal
 			| SaveGoals], InstMapDelta0),
 		instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-		goal_info_init(NonLocals, InstMapDelta, det, pure, Context,
+		goal_info_init(NonLocals, InstMapDelta, det, impure, Context,
 			GoalInfo),
 		Goal = GoalEx - GoalInfo
 	;
@@ -1523,7 +1519,7 @@
 	create_instmap_delta(Goals, InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
 	goal_info_init(NonLocals, InstMapDelta, semidet,
-		pure, Context, GoalInfo),
+		impure, Context, GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 :- pred generate_save_goals(assoc_list(prog_var, int)::in, prog_var::in,
@@ -1617,7 +1613,8 @@
 	set__insert_list(NonLocals0, OutputVars, NonLocals),
 	create_instmap_delta(RestoreGoals, InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, det, pure, Context, GoalInfo),
+	goal_info_init(NonLocals, InstMapDelta, det, semipure, Context,
+		GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 :- pred generate_restore_all_goal(determinism::in,
@@ -1653,8 +1650,8 @@
 	create_instmap_delta([ReturnAnsBlocksGoal | RestoreGoals],
 		InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, nondet,
-		pure, Context, GoalInfo),
+	goal_info_init(NonLocals, InstMapDelta, nondet, semipure, Context,
+		GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 :- pred generate_restore_goals(assoc_list(prog_var, int)::in, prog_var::in,
@@ -1727,18 +1724,21 @@
 	create_instmap_delta([ReturnAnsBlocksGoal | RestoreGoals],
 		InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, nondet,
-		pure, Context, GoalInfo),
+	goal_info_init(NonLocals, InstMapDelta, nondet, impure, Context,
+		GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
 %-----------------------------------------------------------------------------%
 
+:- func infinite_recursion_msg = string.
+
+infinite_recursion_msg = "detected infinite recursion".
+
 :- pred generate_loop_error_goal(table_info::in, term__context::in,
-	map(prog_var, type)::in, map(prog_var, type)::out,
+	string::in, map(prog_var, type)::in, map(prog_var, type)::out,
 	prog_varset::in, prog_varset::out, hlds_goal::out) is det.
 
-generate_loop_error_goal(TableInfo, Context, VarTypes0, VarTypes,
-		VarSet0, VarSet, Goal) :-
+generate_loop_error_goal(TableInfo, Context, Msg, !VarTypes, !VarSet, Goal) :-
 	ModuleInfo = TableInfo ^ table_module_info,
 	PredInfo = TableInfo ^ table_cur_pred_info,
 
@@ -1749,20 +1749,19 @@
 	hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncS),
 	prog_out__sym_name_to_string(qualified(Module, Name), NameS),
 	string__int_to_string(Arity, ArityS),
-	string__append_list(["detected infinite recursion in ", PredOrFuncS,
+	string__append_list([Msg, " in ", PredOrFuncS,
 		" ", NameS, "/", ArityS], Message),
 
-	gen_string_construction("MessageS", Message, VarTypes0, VarTypes,
-		VarSet0, VarSet, MessageVar, MessageConsGoal),
+	gen_string_construction("MessageS", Message, !VarTypes, !VarSet,
+		MessageVar, MessageConsGoal),
 	generate_call("table_loopcheck_error", [MessageVar], erroneous,
 		no, [], ModuleInfo, Context, CallGoal),
 
 	GoalEx = conj([MessageConsGoal, CallGoal]),
 	set__init(NonLocals),
-	create_instmap_delta([MessageConsGoal, CallGoal],
-		InstMapDelta0),
+	create_instmap_delta([MessageConsGoal, CallGoal], InstMapDelta0),
 	instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-	goal_info_init(NonLocals, InstMapDelta, erroneous, pure,
+	goal_info_init(NonLocals, InstMapDelta, erroneous, impure,
 		Context, GoalInfo),
 	Goal = GoalEx - GoalInfo.
 
@@ -1795,8 +1794,8 @@
 	goal_info_get_nonlocals(GoalInfo, NonLocals),
 	goal_info_get_context(GoalInfo, Context),
 	instmap_delta_init_unreachable(UnreachInstMapDelta),
-	goal_info_init(NonLocals, UnreachInstMapDelta, failure, pure, Context,
-		ConjGoalInfo),
+	goal_info_init(NonLocals, UnreachInstMapDelta, failure, impure,
+		Context, ConjGoalInfo),
 	fail_goal(FailGoal),
 	GoalAndThenFail = conj([Goal, FailGoal]) - ConjGoalInfo.
 
@@ -1823,6 +1822,12 @@
 :- func node_type = (type).
 
 node_type = c_pointer_type.
+
+:- func status_type = (type).
+
+status_type = Type :-
+	mercury_table_builtin_module(TB),
+	construct_type(qualified(TB, "subgoal_status") - 0, [], Type).
 
 :- pred get_input_output_vars(list(prog_var)::in, list(mode)::in,
 	module_info::in, list(prog_var)::out, list(prog_var)::out) is det.
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.360
diff -u -b -r1.360 user_guide.texi
--- doc/user_guide.texi	11 Mar 2003 02:44:21 -0000	1.360
+++ doc/user_guide.texi	13 Mar 2003 06:50:03 -0000
@@ -3183,10 +3183,35 @@
 of the Mercury implementation.
 @sp 1
 @table @code
+ at item subgoal @var{n}
+ at kindex subgoal (mdb command)
+In minimal model grades,
+prints the details of the specified subgoal.
+In other grades, it reports an error.
+ at sp 1
+ at item consumer @var{n}
+ at kindex consumer (mdb command)
+In minimal model grades,
+prints the details of the specified consumer.
+In other grades, it reports an error.
+ at sp 1
 @item gen_stack
 @kindex gen_stack (mdb command)
-Prints the contents of the frames on the generator stack,
-which is part of the implementation of minimal model tabling.
+In minimal model grades,
+prints the contents of the frames on the generator stack.
+In other grades, it reports an error.
+ at sp 1
+ at item cut_stack
+ at kindex cut_stack (mdb command)
+In minimal model grades,
+prints the contents of the frames on the cut stack.
+In other grades, it reports an error.
+ at sp 1
+ at item pneg_stack
+ at kindex pneg_stack (mdb command)
+In minimal model grades,
+prints the contents of the frames on the possible negated context stack.
+In other grades, it reports an error.
 @sp 1
 @item nondet_stack [-d]
 @kindex nondet_stack (mdb command)
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
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/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/graphics
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/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing java
cvs diff: Diffing java/library
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/table_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/table_builtin.m,v
retrieving revision 1.27
diff -u -b -r1.27 table_builtin.m
--- library/table_builtin.m	3 Mar 2003 03:29:38 -0000	1.27
+++ library/table_builtin.m	12 Mar 2003 08:30:07 -0000
@@ -685,6 +685,17 @@
 :- semipure pred table_multi_return_all_ans(ml_subgoal_table_node::in,
 	ml_answer_block::out) is multi.
 
+	% This type should correspond exactly to the type MR_SubgoalStatus
+	% defined in runtime/mercury_tabling.h.
+
+:- type subgoal_status
+	--->	inactive
+	;	active
+	;	complete.
+
+:- semipure pred table_subgoal_status(ml_subgoal_table_node::in,
+	subgoal_status::out) is det.
+
 	% N.B. interface continued below
 
 %-----------------------------------------------------------------------------%
@@ -721,25 +732,51 @@
 
 		subgoal = MR_TABLE_NEW(MR_Subgoal);
 
-		subgoal->status = MR_SUBGOAL_INACTIVE;
-		subgoal->leader = NULL;
-		subgoal->followers = MR_TABLE_NEW(MR_SubgoalListNode);
-		subgoal->followers->item = subgoal;
-		subgoal->followers->next = NULL;
-		subgoal->followers_tail = &(subgoal->followers->next);
-		subgoal->answer_table = (MR_Word) NULL;
-		subgoal->num_ans = 0;
-		subgoal->answer_list = NULL;
-		subgoal->answer_list_tail = &subgoal->answer_list;
-		subgoal->consumer_list = NULL;
-		subgoal->consumer_list_tail = &subgoal->consumer_list;
+		subgoal->MR_sg_status = MR_SUBGOAL_INACTIVE;
+		subgoal->MR_sg_leader = NULL;
+		subgoal->MR_sg_followers = MR_TABLE_NEW(MR_SubgoalListNode);
+		subgoal->MR_sg_followers->MR_sl_item = subgoal;
+		subgoal->MR_sg_followers->MR_sl_next = NULL;
+		subgoal->MR_sg_followers_tail =
+			&(subgoal->MR_sg_followers->MR_sl_next);
+		subgoal->MR_sg_answer_table = (MR_Word) NULL;
+		subgoal->MR_sg_num_ans = 0;
+		subgoal->MR_sg_answer_list = NULL;
+		subgoal->MR_sg_answer_list_tail =
+			&subgoal->MR_sg_answer_list;
+		subgoal->MR_sg_consumer_list = NULL;
+		subgoal->MR_sg_consumer_list_tail =
+			&subgoal->MR_sg_consumer_list;
 
 #ifdef	MR_TABLE_DEBUG
+		/*
+		** MR_subgoal_debug_cur_proc refers to the last procedure
+		** that executed a call event, if any. If the procedure that is
+		** executing table_nondet_setup is traced, this will be that
+		** procedure, and recording the layout structure of the
+		** processor in the subgoal allows us to interpret the contents
+		** of the subgoal's answer tables. If the procedure executing
+		** table_nondet_setup is not traced, then the layout structure
+		** belongs to another procedure and the any use of the
+		** MR_sg_proc_layout field will probably cause a core dump.
+		** For implementors debugging minimal model tabling, this is
+		** the right tradeoff.
+		*/
+		subgoal->MR_sg_proc_layout = MR_subgoal_debug_cur_proc;
+
+		MR_enter_subgoal_debug(subgoal);
+
 		if (MR_tabledebug) {
-			printf(""setting up table %p -> %p, "",
-				table, subgoal);
+			printf(""setting up subgoal %p -> %s, "",
+				table, MR_subgoal_addr_name(subgoal));
 			printf(""answer slot %p\\n"",
-				subgoal->answer_list_tail);
+				subgoal->MR_sg_answer_list_tail);
+			if (subgoal->MR_sg_proc_layout != NULL) {
+				printf(""proc: "");
+				MR_print_proc_id(stdout,
+					subgoal->MR_sg_proc_layout);
+				printf(""\\n"");
+			}
 		}
 
 		if (MR_maxfr != MR_curfr) {
@@ -747,13 +784,7 @@
 				""MR_maxfr != MR_curfr at table setup\\n"");
 		}
 #endif
-#ifdef MR_HIGHLEVEL_CODE
- 		MR_fatal_error(""sorry, not implemented: ""
-			""minimal_model tabling with --high-level-code"");
-#else
-		subgoal->generator_maxfr = MR_prevfr_slot(MR_maxfr);
-		subgoal->generator_sp = MR_sp;
-#endif
+		subgoal->MR_sg_generator_fr = MR_curfr;
 		table->MR_subgoal = subgoal;
 	}
 	T = T0;
@@ -801,7 +832,7 @@
 	table = T;
 
 	SUCCESS_INDICATOR =
-		(table->MR_subgoal->status == MR_SUBGOAL_COMPLETE);
+		(table->MR_subgoal->MR_sg_status == MR_SUBGOAL_COMPLETE);
 #else
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #endif
@@ -817,7 +848,7 @@
 	table = T;
 
 	SUCCESS_INDICATOR =
-		(table->MR_subgoal->status == MR_SUBGOAL_ACTIVE);
+		(table->MR_subgoal->MR_sg_status == MR_SUBGOAL_ACTIVE);
 #else
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #endif
@@ -834,7 +865,7 @@
 
 	MR_push_generator(MR_curfr, table);
 	MR_register_generator_ptr(table);
-	table->MR_subgoal->status = MR_SUBGOAL_ACTIVE;
+	table->MR_subgoal->MR_sg_status = MR_SUBGOAL_ACTIVE;
 #else
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #endif
@@ -849,7 +880,7 @@
 
 	table = T;
 
-	AT = (MR_TrieNode) &(table->MR_subgoal->answer_table);
+	AT = (MR_TrieNode) &(table->MR_subgoal->MR_sg_answer_table);
 #else
 	MR_fatal_error(""minimal model code entered when not enabled"");
 #endif
@@ -893,7 +924,7 @@
 
 	table = T;
 	subgoal = table->MR_subgoal;
-	subgoal->num_ans++;
+	subgoal->MR_sg_num_ans++;
 
 	/*
 	**
@@ -903,22 +934,25 @@
 	*/
 
 	answer_node = MR_TABLE_NEW(MR_AnswerListNode);
-	answer_node->answer_num = subgoal->num_ans;
-	answer_node->answer_data.MR_integer = 0;
-	answer_node->next_answer = NULL;
+	answer_node->MR_aln_answer_num = subgoal->MR_sg_num_ans;
+	answer_node->MR_aln_answer_data.MR_integer = 0;
+	answer_node->MR_aln_next_answer = NULL;
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
-		printf(""new answer slot %d at %p(%p), storing into %p\\n"",
-			subgoal->num_ans, answer_node,
-			&answer_node->answer_data, subgoal->answer_list_tail);
+		printf(""%s: new answer slot %d at %p(%p)\n"",
+			MR_subgoal_addr_name(subgoal),
+			subgoal->MR_sg_num_ans, answer_node,
+			&answer_node->MR_aln_answer_data);
+		printf(""\tstoring into %p\\n"",
+			subgoal->MR_sg_answer_list_tail);
 	}
 #endif
 
-	*(subgoal->answer_list_tail) = answer_node;
-	subgoal->answer_list_tail = &(answer_node->next_answer);
+	*(subgoal->MR_sg_answer_list_tail) = answer_node;
+	subgoal->MR_sg_answer_list_tail = &(answer_node->MR_aln_next_answer);
 
-	Slot = (MR_Word) &(answer_node->answer_data);
+	Slot = (MR_TrieNode) &(answer_node->MR_aln_answer_data);
 #endif
 ").
 
@@ -961,12 +995,12 @@
 	MR_TrieNode	table;
 
 	table = T;
-	CurNode = table->MR_subgoal->answer_list;
+	CurNode = table->MR_subgoal->MR_sg_answer_list;
 
   #ifdef MR_TABLE_DEBUG
 	if (MR_tabledebug) {
-		printf(""restoring all answers in %p -> %p\\n"",
-			table, table->MR_subgoal);
+		printf(""restoring all answers in %p -> %s\\n"",
+			table, MR_subgoal_addr_name(table->MR_subgoal));
 	}
   #endif
 #else
@@ -985,8 +1019,8 @@
 	if (CurNode0 == NULL) {
 		SUCCESS_INDICATOR = MR_FALSE;
 	} else {
-		AnswerBlock = &CurNode0->answer_data;
-		CurNode = CurNode0->next_answer;
+		AnswerBlock = &CurNode0->MR_aln_answer_data;
+		CurNode = CurNode0->MR_aln_next_answer;
 		SUCCESS_INDICATOR = MR_TRUE;
 	}
 #else
@@ -994,6 +1028,17 @@
 #endif
 ").
 
+:- pragma foreign_proc("C",
+	table_subgoal_status(T::in, Status::out),
+	[will_not_call_mercury],
+"
+#ifdef MR_USE_MINIMAL_MODEL
+	Status = MR_CONVERT_C_ENUM_CONSTANT(T->MR_subgoal->MR_sg_status);
+#else
+	MR_fatal_error(""minimal model code entered when not enabled"");
+#endif
+").
+
 :- pragma promise_semipure(table_nondet_is_complete/1).
 table_nondet_is_complete(_) :-
 	% This version is only used for back-ends for which there is no
@@ -1045,6 +1090,13 @@
 	% matching foreign_proc version.
 	impure private_builtin__imp,
 	private_builtin__sorry("return_next_answer").
+
+:- pragma promise_semipure(table_subgoal_status/2).
+table_subgoal_status(_, _) :-
+	% This version is only used for back-ends for which there is no
+	% matching foreign_proc version.
+	impure private_builtin__imp,
+	private_builtin__sorry("table_subgoal_status").
 
 %-----------------------------------------------------------------------------%
 
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.101
diff -u -b -r1.101 Mmakefile
--- runtime/Mmakefile	13 Mar 2003 01:47:03 -0000	1.101
+++ runtime/Mmakefile	14 Mar 2003 05:00:21 -0000
@@ -14,8 +14,8 @@
 			mercury_accurate_gc.h	\
 			mercury_agc_debug.h	\
 			mercury_array_macros.h	\
-			mercury_builtin_types.h	\
 			mercury_bootstrap.h	\
+			mercury_builtin_types.h	\
 			mercury_calls.h		\
 			mercury_conf.h		\
 			mercury_conf_bootstrap.h \
@@ -28,8 +28,8 @@
 			mercury_deep_copy.h	\
 			mercury_deep_profiling.h \
 			mercury_deep_profiling_hand.h \
-			mercury_dummy.h		\
 			mercury_dlist.h		\
+			mercury_dummy.h		\
 			mercury_dword.h		\
 		  	mercury_engine.h	\
 			mercury_file.h		\
@@ -48,8 +48,9 @@
 			mercury_layout_util.h	\
 			mercury_library_types.h	\
 			mercury_memory.h	\
-			mercury_memory_zones.h	\
 			mercury_memory_handlers.h	\
+			mercury_memory_zones.h	\
+			mercury_minimal_model.h	\
 			mercury_misc.h		\
 			mercury_overflow.h	\
 			mercury_prof.h		\
@@ -61,10 +62,10 @@
 			mercury_regs.h		\
 			mercury_runtime_util.h	\
 			mercury_signal.h	\
-			mercury_std.h		\
 			mercury_stack_layout.h	\
 			mercury_stack_trace.h	\
 			mercury_stacks.h	\
+			mercury_std.h		\
 			mercury_string.h	\
 			mercury_tabling.h	\
 			mercury_tabling_macros.h	\
@@ -73,10 +74,10 @@
 			mercury_timing.h	\
 			mercury_trace_base.h	\
 			mercury_trail.h		\
-			mercury_types.h		\
 			mercury_type_desc.h	\
 			mercury_type_info.h	\
 			mercury_type_tables.h	\
+			mercury_types.h		\
 			mercury_wrapper.h	\
 			$(LIB_DLL_H)
 
@@ -146,6 +147,7 @@
 			mercury_memory.c	\
 			mercury_memory_handlers.c	\
 			mercury_memory_zones.c	\
+			mercury_minimal_model.c	\
 			mercury_misc.c		\
 			mercury_prof.c		\
 			mercury_prof_mem.c	\
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.35
diff -u -b -r1.35 mercury_context.c
--- runtime/mercury_context.c	12 Mar 2003 06:19:04 -0000	1.35
+++ runtime/mercury_context.c	12 Mar 2003 06:19:37 -0000
@@ -129,10 +129,9 @@
 	if (c->MR_ctxt_genstack_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_genstack_zone);
 	} else {
-		c->MR_ctxt_genstack_zone = MR_create_zone(
-			"generatorstack", 0,
-			MR_generatorstack_size, MR_next_offset(),
-			MR_generatorstack_zone_size, MR_default_handler);
+		c->MR_ctxt_genstack_zone = MR_create_zone("genstack", 0,
+			MR_genstack_size, MR_next_offset(),
+			MR_genstack_zone_size, MR_default_handler);
 	}
 	c->MR_ctxt_gen_next = 0;
 
@@ -144,6 +143,15 @@
 			MR_cutstack_zone_size, MR_default_handler);
 	}
 	c->MR_ctxt_cut_next = 0;
+
+	if (c->MR_ctxt_pnegstack_zone != NULL) {
+		MR_reset_redzone(c->MR_ctxt_pnegstack_zone);
+	} else {
+		c->MR_ctxt_pnegstack_zone = MR_create_zone("pnegstack", 0,
+			MR_pnegstack_size, MR_next_offset(),
+			MR_pnegstack_zone_size, MR_default_handler);
+	}
+	c->MR_ctxt_pneg_next = 0;
   #endif /* MR_USE_MINIMAL_MODEL */
 #endif /* !MR_HIGHLEVEL_CODE */
 
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.22
diff -u -b -r1.22 mercury_context.h
--- runtime/mercury_context.h	21 Aug 2002 11:27:41 -0000	1.22
+++ runtime/mercury_context.h	13 Dec 2002 03:59:06 -0000
@@ -111,6 +111,10 @@
 		/* pointer to the cutstack_zone for this context */
 	MR_Integer	MR_ctxt_cut_next;
 		/* saved cut stack index for this context */
+	MR_MemoryZone	*MR_ctxt_pnegstack_zone;
+		/* pointer to the pnegstack_zone for this context */
+	MR_Integer	MR_ctxt_pneg_next;
+		/* saved pneg stack index for this context */
   #endif /* MR_USE_MINIMAL_MODEL */
 #endif /* !MR_HIGHLEVEL_CODE */
 
@@ -352,6 +356,7 @@
 		  MR_IF_USE_MINIMAL_MODEL(				\
 			MR_gen_next = load_context_c->MR_ctxt_gen_next;	\
 			MR_cut_next = load_context_c->MR_ctxt_cut_next;	\
+			MR_pneg_next = load_context_c->MR_ctxt_pneg_next;\
 		  )							\
 		)							\
 	        MR_IF_USE_TRAIL(					\
@@ -372,12 +377,17 @@
 				load_context_c->MR_ctxt_genstack_zone;	\
 		    MR_ENGINE(MR_eng_context).MR_ctxt_cutstack_zone =   \
 				load_context_c->MR_ctxt_cutstack_zone;	\
-		    MR_gen_stack = (MR_GeneratorStackFrame *)		\
+		    MR_ENGINE(MR_eng_context).MR_ctxt_pnegstack_zone =  \
+				load_context_c->MR_ctxt_pnegstack_zone;	\
+		    MR_gen_stack = (MR_GenStackFrame *)			\
 				MR_ENGINE(MR_eng_context).		\
 					MR_ctxt_genstack_zone;		\
 		    MR_cut_stack = (MR_CutStackFrame *)			\
 				MR_ENGINE(MR_eng_context).		\
 					MR_ctxt_cutstack_zone;		\
+		    MR_pneg_stack = (MR_PNegStackFrame *)		\
+				MR_ENGINE(MR_eng_context).		\
+					MR_ctxt_pnegstack_zone;		\
 	    	  )							\
 	    	)							\
 		MR_set_min_heap_reclamation_point(load_context_c);	\
@@ -396,6 +406,7 @@
 		  MR_IF_USE_MINIMAL_MODEL(				\
 			save_context_c->MR_ctxt_gen_next = MR_gen_next;	\
 			save_context_c->MR_ctxt_cut_next = MR_cut_next;	\
+			save_context_c->MR_ctxt_pneg_next = MR_pneg_next;\
 		  )							\
 		)							\
 		MR_IF_USE_TRAIL(					\
@@ -420,12 +431,18 @@
 		    save_context_c->MR_ctxt_cutstack_zone =		\
 				MR_ENGINE(MR_eng_context).		\
 					MR_ctxt_cutstack_zone;		\
-		    assert(MR_gen_stack == (MR_GeneratorStackFrame *)	\
+		    save_context_c->MR_ctxt_pnegstack_zone =		\
+				MR_ENGINE(MR_eng_context).		\
+					MR_ctxt_pnegstack_zone;		\
+		    assert(MR_gen_stack == (MR_GenStackFrame *)		\
 				MR_ENGINE(MR_eng_context).		\
 					MR_ctxt_genstack_zone);		\
 		    assert(MR_cut_stack == (MR_CutStackFrame *)		\
 				MR_ENGINE(MR_eng_context).		\
 					MR_ctxt_cutstack_zone);		\
+		    assert(MR_pneg_stack == (MR_PNegStackFrame *)	\
+				MR_ENGINE(MR_eng_context).		\
+					MR_ctxt_pnegstack_zone);	\
 		  )							\
 		)							\
 		MR_save_hp_in_context(save_context_c);			\
Index: runtime/mercury_debug.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_debug.c,v
retrieving revision 1.13
diff -u -b -r1.13 mercury_debug.c
--- runtime/mercury_debug.c	17 Jan 2003 05:56:50 -0000	1.13
+++ runtime/mercury_debug.c	14 Mar 2003 04:39:01 -0000
@@ -681,7 +681,7 @@
 void 
 MR_print_detstackptr(FILE *fp, const MR_Word *s)
 {
-	fprintf(fp, "det %3ld ",
+	fprintf(fp, "det %3ld",
 		(long) (MR_Integer)
 			(s - MR_CONTEXT(MR_ctxt_detstack_zone)->min));
 
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.40
diff -u -b -r1.40 mercury_engine.c
--- runtime/mercury_engine.c	3 Mar 2003 09:03:16 -0000	1.40
+++ runtime/mercury_engine.c	12 Mar 2003 08:09:52 -0000
@@ -37,6 +37,27 @@
 
 MR_bool	MR_debugflag[MR_MAXFLAG];
 
+MR_Debug_Flag_Info	MR_debug_flag_info[MR_MAXFLAG] = {
+	{ "prog",	MR_PROGFLAG },
+	{ "goto",	MR_GOTOFLAG },
+	{ "call",	MR_CALLFLAG },
+	{ "heap",	MR_HEAPFLAG },
+	{ "detstack",	MR_DETSTACKFLAG },
+	{ "nondstack",	MR_NONDSTACKFLAG },
+	{ "final",	MR_FINALFLAG },
+	{ "mem",	MR_MEMFLAG },
+	{ "sreg",	MR_SREGFLAG },
+	{ "trace",	MR_TRACEFLAG },
+	{ "table",	MR_TABLEFLAG },
+	{ "hash",	MR_TABLEHASHFLAG },
+	{ "tablestack",	MR_TABLESTACKFLAG },
+	{ "unbuf",	MR_UNBUFFLAG },
+	{ "agc",	MR_AGC_FLAG },
+	{ "ordreg",	MR_ORDINARY_REG_FLAG },
+	{ "anyreg",	MR_ANY_REG_FLAG },
+	{ "detail",	MR_DETAILFLAG }
+};
+
 #ifndef MR_THREAD_SAFE
   MercuryEngine	MR_engine_base;
 #endif
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.28
diff -u -b -r1.28 mercury_engine.h
--- runtime/mercury_engine.h	3 Mar 2003 09:03:16 -0000	1.28
+++ runtime/mercury_engine.h	12 Mar 2003 08:40:19 -0000
@@ -39,7 +39,8 @@
 
 /*
 ** These #defines, except MR_MAXFLAG, should not be used anywhere
-** except in the immediately following block of #defines.
+** except in the immediately following block of #defines, and in the
+** array that maps these names to their slots in the source file.
 */
 
 #define	MR_PROGFLAG		0
@@ -131,6 +132,13 @@
 #define	MR_ordregdebug		MR_debugflag[MR_ORDINARY_REG_FLAG]
 #define	MR_anyregdebug		MR_debugflag[MR_ANY_REG_FLAG]
 #define	MR_detaildebug		MR_debugflag[MR_DETAILFLAG]
+
+typedef struct {
+	const char		*MR_debug_flag_name;
+	int			MR_debug_flag_index;
+} MR_Debug_Flag_Info;
+
+extern	MR_Debug_Flag_Info	MR_debug_flag_info[MR_MAXFLAG];
 
 	/* 
 	** MR_setjmp and MR_longjmp are wrappers around setjmp and longjmp 
Index: runtime/mercury_imp.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_imp.h,v
retrieving revision 1.19
diff -u -b -r1.19 mercury_imp.h
--- runtime/mercury_imp.h	13 Feb 2002 09:56:40 -0000	1.19
+++ runtime/mercury_imp.h	7 Mar 2003 10:18:52 -0000
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1993-1998, 2000 The University of Melbourne.
+** Copyright (C) 1993-1998,2000,2003 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
@@ -80,8 +80,10 @@
 #include	"mercury_misc.h"
 
 #include	"mercury_tabling.h"
+#ifdef MR_USE_MINIMAL_MODEL
+#include	"mercury_minimal_model.h"
+#endif
 
 #include	"mercury_grade.h"
-
 
 #endif /* not MERCURY_IMP_H */
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.31
diff -u -b -r1.31 mercury_memory.c
--- runtime/mercury_memory.c	21 Aug 2002 11:27:43 -0000	1.31
+++ runtime/mercury_memory.c	7 Dec 2002 13:40:27 -0000
@@ -103,8 +103,9 @@
 */
 
 #ifdef	MR_USE_MINIMAL_MODEL
-  MR_MemoryZone *MR_generatorstack_zone;
+  MR_MemoryZone *MR_genstack_zone;
   MR_MemoryZone *MR_cutstack_zone;
+  MR_MemoryZone *MR_pnegstack_zone;
 #endif
 
 size_t		MR_unit;
@@ -168,14 +169,18 @@
 	MR_nondstack_zone_size	 = MR_round_up(MR_nondstack_zone_size * 1024,
 					MR_unit);
 #ifdef	MR_USE_MINIMAL_MODEL
-	MR_generatorstack_size	 = MR_round_up(MR_generatorstack_size * 1024,
+	MR_genstack_size	 = MR_round_up(MR_genstack_size * 1024,
 					MR_unit);
-	MR_generatorstack_zone_size = MR_round_up(
-					MR_generatorstack_zone_size * 1024,
+	MR_genstack_zone_size = MR_round_up(
+					MR_genstack_zone_size * 1024,
 					MR_unit);
 	MR_cutstack_size	 = MR_round_up(MR_cutstack_size * 1024,
 					MR_unit);
 	MR_cutstack_zone_size	 = MR_round_up(MR_cutstack_zone_size * 1024,
+					MR_unit);
+	MR_pnegstack_size	 = MR_round_up(MR_pnegstack_size * 1024,
+					MR_unit);
+	MR_pnegstack_zone_size	 = MR_round_up(MR_pnegstack_zone_size * 1024,
 					MR_unit);
 #endif
 
Index: runtime/mercury_minimal_model.c
===================================================================
RCS file: runtime/mercury_minimal_model.c
diff -N runtime/mercury_minimal_model.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_minimal_model.c	14 Mar 2003 04:49:43 -0000
@@ -0,0 +1,1574 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 2003 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This module contains the functions related specifically to minimal model
+** tabling.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_array_macros.h"
+#include "mercury_tabling.h"
+#include "mercury_minimal_model.h"
+
+#include <stdio.h>
+
+#ifdef  MR_USE_MINIMAL_MODEL
+
+static  MR_Word *nearest_common_ancestor(MR_Word *fr1, MR_Word *fr2);
+static  void    save_state(MR_SavedState *saved_state, MR_Word *generator_fr,
+                    const char *who, const char *what);
+static  void    restore_state(MR_SavedState *saved_state, const char *who,
+                    const char *what);
+static  void    extend_consumer_stacks(MR_Subgoal *leader,
+                    MR_Consumer *suspension);
+static  void    make_subgoal_follow_leader(MR_Subgoal *this_follower,
+                    MR_Subgoal *leader);
+static  void    print_saved_state(FILE *fp, MR_SavedState *saved_state);
+static  void    print_stack_segment(FILE *fp, MR_Word *segment,
+                    MR_Integer size);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** This part of the file maintains data structures that can be used
+** to debug minimal model tabling. It does so by allowing the debugger
+** to refer to tabling data structures such as subgoals and consumers
+** by small, easily remembered numbers, not memory addresses.
+*/
+
+/* set by MR_trace_event, used by table_nondet_setup */
+MR_Proc_Layout          *MR_subgoal_debug_cur_proc = NULL;
+
+struct MR_ConsumerDebug_Struct
+{
+    MR_Consumer *MR_cod_consumer;
+    int         MR_cod_sequence_num;
+    int         MR_cod_version_num;
+    int         MR_cod_valid;
+};
+
+struct MR_SubgoalDebug_Struct
+{
+    MR_Subgoal  *MR_sgd_subgoal;
+    int         MR_sgd_sequence_num;
+    int         MR_sgd_version_num;
+    int         MR_sgd_valid;
+};
+
+#define MR_CONSUMER_DEBUG_INIT  10
+#define MR_SUBGOAL_DEBUG_INIT   10
+#define MR_NAME_BUF             1024
+
+static  MR_ConsumerDebug *MR_consumer_debug_infos = NULL;
+static  int             MR_consumer_debug_info_next = 0;
+static  int             MR_consumer_debug_info_max  = 0;
+
+static  MR_SubgoalDebug *MR_subgoal_debug_infos = NULL;
+static  int             MR_subgoal_debug_info_next = 0;
+static  int             MR_subgoal_debug_info_max  = 0;
+
+void
+MR_enter_consumer_debug(MR_Consumer *consumer)
+{
+    int i;
+
+    for (i = 0; i < MR_consumer_debug_info_next; i++) {
+        if (MR_consumer_debug_infos[i].MR_cod_consumer == consumer) {
+            MR_consumer_debug_infos[i].MR_cod_version_num++;
+            MR_consumer_debug_infos[i].MR_cod_valid = MR_TRUE;
+            return;
+        }
+    }
+
+    MR_ensure_room_for_next(MR_consumer_debug_info, MR_ConsumerDebug,
+        MR_CONSUMER_DEBUG_INIT);
+    i = MR_consumer_debug_info_next;
+    MR_consumer_debug_infos[i].MR_cod_consumer = consumer;
+    MR_consumer_debug_infos[i].MR_cod_sequence_num = i;
+    MR_consumer_debug_infos[i].MR_cod_version_num = 0;
+    MR_consumer_debug_infos[i].MR_cod_valid = MR_TRUE;
+    MR_consumer_debug_info_next++;
+}
+
+MR_ConsumerDebug *
+MR_lookup_consumer_debug_addr(MR_Consumer *consumer)
+{
+    int i;
+
+    for (i = 0; i < MR_consumer_debug_info_next; i++) {
+        if (MR_consumer_debug_infos[i].MR_cod_consumer == consumer) {
+            return &MR_consumer_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+MR_ConsumerDebug *
+MR_lookup_consumer_debug_num(int consumer_index)
+{
+    int i;
+
+    for (i = 0; i < MR_consumer_debug_info_next; i++) {
+        if (MR_consumer_debug_infos[i].MR_cod_sequence_num == consumer_index) {
+            return &MR_consumer_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+const char *
+MR_consumer_debug_name(MR_ConsumerDebug *consumer_debug)
+{
+    const char  *warning;
+    char        buf[MR_NAME_BUF];
+
+    if (consumer_debug == NULL) {
+        return "unknown";
+    }
+
+    if (consumer_debug->MR_cod_valid) {
+        warning = "";
+    } else {
+        warning = " INVALID";
+    }
+
+    if (consumer_debug->MR_cod_version_num > 0) {
+        sprintf(buf, "con %d/%d (%p)%s", consumer_debug->MR_cod_sequence_num,
+            consumer_debug->MR_cod_version_num,
+            consumer_debug->MR_cod_consumer, warning);
+    } else {
+        sprintf(buf, "con %d (%p)%s", consumer_debug->MR_cod_sequence_num,
+            consumer_debug->MR_cod_consumer, warning);
+    }
+
+    return strdup(buf);
+}
+
+const char *
+MR_consumer_addr_name(MR_Consumer *consumer)
+{
+    MR_ConsumerDebug *consumer_debug;
+
+    if (consumer == NULL) {
+        return "NULL";
+    }
+
+    consumer_debug = MR_lookup_consumer_debug_addr(consumer);
+    return MR_consumer_debug_name(consumer_debug);
+}
+
+const char *
+MR_consumer_num_name(int consumer_index)
+{
+    MR_ConsumerDebug *consumer_debug;
+
+    consumer_debug = MR_lookup_consumer_debug_num(consumer_index);
+    return MR_consumer_debug_name(consumer_debug);
+}
+
+void
+MR_enter_subgoal_debug(MR_Subgoal *subgoal)
+{
+    int i;
+
+    for (i = 0; i < MR_subgoal_debug_info_next; i++) {
+        if (MR_subgoal_debug_infos[i].MR_sgd_subgoal == subgoal) {
+            MR_subgoal_debug_infos[i].MR_sgd_version_num++;
+            MR_subgoal_debug_infos[i].MR_sgd_valid = MR_TRUE;
+            return;
+        }
+    }
+
+    MR_ensure_room_for_next(MR_subgoal_debug_info, MR_SubgoalDebug,
+        MR_SUBGOAL_DEBUG_INIT);
+    i = MR_subgoal_debug_info_next;
+    MR_subgoal_debug_infos[i].MR_sgd_subgoal = subgoal;
+    MR_subgoal_debug_infos[i].MR_sgd_sequence_num = i;
+    MR_subgoal_debug_infos[i].MR_sgd_version_num = 0;
+    MR_subgoal_debug_infos[i].MR_sgd_valid = MR_TRUE;
+    MR_subgoal_debug_info_next++;
+}
+
+MR_SubgoalDebug *
+MR_lookup_subgoal_debug_addr(MR_Subgoal *subgoal)
+{
+    int i;
+
+    for (i = 0; i < MR_subgoal_debug_info_next; i++) {
+        if (MR_subgoal_debug_infos[i].MR_sgd_subgoal == subgoal) {
+            return &MR_subgoal_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+MR_SubgoalDebug *
+MR_lookup_subgoal_debug_num(int subgoal_index)
+{
+    int i;
+
+    for (i = 0; i < MR_subgoal_debug_info_next; i++) {
+        if (MR_subgoal_debug_infos[i].MR_sgd_sequence_num == subgoal_index) {
+            return &MR_subgoal_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+const char *
+MR_subgoal_debug_name(MR_SubgoalDebug *subgoal_debug)
+{
+    const char  *warning;
+    char        buf[MR_NAME_BUF];
+
+    if (subgoal_debug == NULL) {
+        return "unknown";
+    }
+
+    if (subgoal_debug->MR_sgd_valid) {
+        warning = "";
+    } else {
+        warning = " INVALID";
+    }
+
+    if (subgoal_debug->MR_sgd_version_num > 0) {
+        sprintf(buf, "sub %d/%d (%p)%s", subgoal_debug->MR_sgd_sequence_num,
+            subgoal_debug->MR_sgd_version_num,
+            subgoal_debug->MR_sgd_subgoal, warning);
+    } else {
+        sprintf(buf, "sub %d (%p)%s", subgoal_debug->MR_sgd_sequence_num,
+            subgoal_debug->MR_sgd_subgoal, warning);
+    }
+
+    return strdup(buf);
+}
+
+const char *
+MR_subgoal_addr_name(MR_Subgoal *subgoal)
+{
+    MR_SubgoalDebug *subgoal_debug;
+
+    if (subgoal == NULL) {
+        return "NULL";
+    }
+
+    subgoal_debug = MR_lookup_subgoal_debug_addr(subgoal);
+    return MR_subgoal_debug_name(subgoal_debug);
+}
+
+const char *
+MR_subgoal_num_name(int subgoal_index)
+{
+    MR_SubgoalDebug *subgoal_debug;
+
+    subgoal_debug = MR_lookup_subgoal_debug_num(subgoal_index);
+    return MR_subgoal_debug_name(subgoal_debug);
+}
+
+const char *
+MR_subgoal_status(MR_SubgoalStatus status)
+{
+    switch (status) {
+        case MR_SUBGOAL_INACTIVE:
+            return "INACTIVE";
+
+        case MR_SUBGOAL_ACTIVE:
+            return "ACTIVE";
+
+        case MR_SUBGOAL_COMPLETE:
+            return "COMPLETE";
+    }
+
+    return "INVALID";
+}
+
+void
+MR_print_subgoal_debug(FILE *fp, const MR_Proc_Layout *proc,
+    MR_SubgoalDebug *subgoal_debug)
+{
+    if (subgoal_debug == NULL) {
+        fprintf(fp, "NULL subgoal_debug\n");
+    } else {
+        MR_print_subgoal(fp, proc, subgoal_debug->MR_sgd_subgoal);
+    }
+}
+
+void
+MR_print_subgoal(FILE *fp, const MR_Proc_Layout *proc, MR_Subgoal *subgoal)
+{
+    MR_SubgoalList  follower;
+    MR_ConsumerList consumer;
+    MR_AnswerList   answer_list;
+    MR_Word         *answer;
+
+    if (subgoal == NULL) {
+        fprintf(fp, "NULL subgoal\n");
+        return;
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (proc == NULL && subgoal->MR_sg_proc_layout != NULL) {
+        proc = subgoal->MR_sg_proc_layout;
+    }
+#endif
+
+    fprintf(fp, "subgoal %s: status %s, generator frame ",
+        MR_subgoal_addr_name(subgoal),
+        MR_subgoal_status(subgoal->MR_sg_status));
+    MR_print_nondstackptr(fp, subgoal->MR_sg_generator_fr);
+    fprintf(fp, "\n");
+
+    if (proc != NULL) {
+        fprintf(fp, "proc: ");
+        MR_print_proc_id(fp, proc);
+        fprintf(fp, "\n");
+    }
+
+    fprintf(fp, "leader: %s, ",
+        MR_subgoal_addr_name(subgoal->MR_sg_leader));
+    fprintf(fp, "followers:");
+    for (follower = subgoal->MR_sg_followers;
+        follower != NULL; follower = follower->MR_sl_next)
+    {
+        fprintf(fp, " %s", MR_subgoal_addr_name(follower->MR_sl_item));
+    }
+
+    fprintf(fp, "\nconsumers:");
+    for (consumer = subgoal->MR_sg_consumer_list;
+        consumer != NULL; consumer = consumer->MR_cl_next)
+    {
+        fprintf(fp, " %s", MR_consumer_addr_name(consumer->MR_cl_item));
+    }
+
+    fprintf(fp, "\n");
+    fprintf(fp, "answers: %d, committed: %d\n",
+        subgoal->MR_sg_num_ans,
+        subgoal->MR_sg_num_committed_ans);
+
+    if (proc != NULL) {
+        answer_list = subgoal->MR_sg_answer_list;
+        while (answer_list != NULL) {
+            fprintf(fp, "answer #%d: <", answer_list->MR_aln_answer_num);
+            MR_print_answerblock(fp, proc,
+                answer_list->MR_aln_answer_data.MR_answerblock);
+            fprintf(fp, ">\n");
+            answer_list = answer_list->MR_aln_next_answer;
+        }
+    }
+}
+
+void
+MR_print_consumer_debug(FILE *fp, const MR_Proc_Layout *proc,
+    MR_ConsumerDebug *consumer_debug)
+{
+    if (consumer_debug == NULL) {
+        fprintf(fp, "NULL consumer_debug\n");
+    } else {
+        MR_print_consumer(fp, proc, consumer_debug->MR_cod_consumer);
+    }
+}
+
+void
+MR_print_consumer(FILE *fp, const MR_Proc_Layout *proc, MR_Consumer *consumer)
+{
+    if (consumer == NULL) {
+        fprintf(fp, "NULL consumer\n");
+        return;
+    }
+
+    fprintf(fp, "consumer %s", MR_consumer_addr_name(consumer));
+
+#ifdef  MR_TABLE_DEBUG
+    fprintf(fp, ", of subgoal %s",
+        MR_subgoal_addr_name(consumer->MR_cns_subgoal));
+#endif
+
+    fprintf(fp, ", remaining answers %p\n",
+        consumer->MR_cns_remaining_answer_list_ptr);
+    print_saved_state(fp, &consumer->MR_cns_saved_state);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** This part of the file provides the utility functions needed for
+** suspensions and resumptions of derivations.
+*/
+
+#define RESUME_LABEL(name)  MR_PASTE3(MR_RESUME_ENTRY, _, name)
+
+/*
+** Given pointers to two ordinary frames on the nondet stack, return the
+** address of the stack frame of their nearest common ancestor on that stack.
+*/
+
+static MR_Word *
+nearest_common_ancestor(MR_Word *fr1, MR_Word *fr2)
+{
+    while (fr1 != fr2) {
+  #ifdef MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("common ancestor search: ");
+            MR_printnondstackptr(fr1);
+            printf(" vs ");
+            MR_printnondstackptr(fr2);
+            printf("\n");
+        }
+  #endif
+
+        if (fr1 > fr2) {
+            fr1 = MR_succfr_slot(fr1);
+        } else {
+            fr2 = MR_succfr_slot(fr2);
+        }
+    }
+
+  #ifdef MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("the common ancestor is ");
+        MR_printnondstackptr(fr1);
+        printf("\n");
+    }
+  #endif
+
+    return fr1;
+}
+
+/*
+** Save the current state of the Mercury abstract machine, so that the
+** current computation may be suspended for a while, and restored later.
+** The generator_fr argument gives the point from which we need to copy the
+** nondet and (indirectly) the det stacks. The parts of those stacks below
+** the given points will not change between the suspension and the resumption
+** of this state, or if they do, the stack segments in the saved state
+** will be extended (via extend_consumer_stacks).
+*/
+
+static void
+save_state(MR_SavedState *saved_state, MR_Word *generator_fr,
+    const char *who, const char *what)
+{
+    MR_Word *common_ancestor_fr;
+    MR_Word *start_non;
+    MR_Word *start_det;
+
+    MR_restore_transient_registers();
+
+    common_ancestor_fr = nearest_common_ancestor(MR_curfr, generator_fr);
+    start_non = MR_prevfr_slot(common_ancestor_fr) + 1;
+    start_det = MR_table_detfr_slot(common_ancestor_fr) + 1;
+
+    saved_state->MR_ss_succ_ip = MR_succip;
+    saved_state->MR_ss_s_p = MR_sp;
+    saved_state->MR_ss_cur_fr = MR_curfr;
+    saved_state->MR_ss_max_fr = MR_maxfr;
+    saved_state->MR_ss_common_ancestor_fr = common_ancestor_fr;
+
+    /* we copy from start_non to MR_maxfr, both inclusive */
+    saved_state->MR_ss_non_stack_real_start = start_non;
+    if (MR_maxfr >= start_non) {
+        saved_state->MR_ss_non_stack_block_size = MR_maxfr + 1 - start_non;
+        saved_state->MR_ss_non_stack_saved_block = MR_table_allocate_words(
+            saved_state->MR_ss_non_stack_block_size);
+        MR_table_copy_words(saved_state->MR_ss_non_stack_saved_block,
+            saved_state->MR_ss_non_stack_real_start,
+            saved_state->MR_ss_non_stack_block_size);
+    } else {
+        saved_state->MR_ss_non_stack_block_size = 0;
+        saved_state->MR_ss_non_stack_saved_block = NULL;
+    }
+
+    /* we copy from start_det to MR_sp, both inclusive */
+    saved_state->MR_ss_det_stack_real_start = start_det;
+    if (MR_sp >= start_det) {
+        saved_state->MR_ss_det_stack_block_size = MR_sp + 1 - start_det;
+        saved_state->MR_ss_det_stack_saved_block = MR_table_allocate_words(
+            saved_state->MR_ss_det_stack_block_size);
+        MR_table_copy_words(saved_state->MR_ss_det_stack_saved_block,
+            saved_state->MR_ss_det_stack_real_start,
+            saved_state->MR_ss_det_stack_block_size);
+    } else {
+        saved_state->MR_ss_det_stack_block_size = 0;
+        saved_state->MR_ss_det_stack_saved_block = NULL;
+    }
+
+    saved_state->MR_ss_gen_next = MR_gen_next;
+    saved_state->MR_ss_gen_stack_saved_block = MR_table_allocate_structs(
+        saved_state->MR_ss_gen_next, MR_GenStackFrame);
+    MR_table_copy_structs(saved_state->MR_ss_gen_stack_saved_block,
+        MR_gen_stack, saved_state->MR_ss_gen_next, MR_GenStackFrame);
+
+    saved_state->MR_ss_cut_next = MR_cut_next;
+    saved_state->MR_ss_cut_stack_saved_block = MR_table_allocate_structs(
+        MR_cut_next, MR_CutStackFrame);
+    MR_table_copy_structs(saved_state->MR_ss_cut_stack_saved_block,
+        MR_cut_stack, saved_state->MR_ss_cut_next, MR_CutStackFrame);
+
+    saved_state->MR_ss_pneg_next = MR_pneg_next;
+    saved_state->MR_ss_pneg_stack_saved_block = MR_table_allocate_structs(
+        MR_pneg_next, MR_PNegStackFrame);
+    MR_table_copy_structs(saved_state->MR_ss_pneg_stack_saved_block,
+        MR_pneg_stack, saved_state->MR_ss_pneg_next, MR_PNegStackFrame);
+
+  #ifdef MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("\n%s saves %s stacks\n", who, what);
+        print_saved_state(stdout, saved_state);
+    }
+
+    if (MR_tablestackdebug) {
+        MR_dump_nondet_stack(stdout, MR_maxfr);
+    }
+  #endif /* MR_TABLE_DEBUG */
+
+    MR_save_transient_registers();
+}
+
+/*
+** Restore the state of the Mercury abstract machine from saved_state.
+*/
+
+static void
+restore_state(MR_SavedState *saved_state, const char *who, const char *what)
+{
+    MR_restore_transient_registers();
+
+    MR_succip = saved_state->MR_ss_succ_ip;
+    MR_sp = saved_state->MR_ss_s_p;
+    MR_curfr = saved_state->MR_ss_cur_fr;
+    MR_maxfr = saved_state->MR_ss_max_fr;
+
+    MR_table_copy_words(saved_state->MR_ss_non_stack_real_start,
+        saved_state->MR_ss_non_stack_saved_block,
+        saved_state->MR_ss_non_stack_block_size);
+
+    MR_table_copy_words(saved_state->MR_ss_det_stack_real_start,
+        saved_state->MR_ss_det_stack_saved_block,
+        saved_state->MR_ss_det_stack_block_size);
+
+    MR_gen_next = saved_state->MR_ss_gen_next;
+    MR_table_copy_structs(MR_gen_stack,
+        saved_state->MR_ss_gen_stack_saved_block,
+        saved_state->MR_ss_gen_next, MR_GenStackFrame);
+
+    MR_cut_next = saved_state->MR_ss_cut_next;
+    MR_table_copy_structs(MR_cut_stack,
+        saved_state->MR_ss_cut_stack_saved_block,
+        saved_state->MR_ss_cut_next, MR_CutStackFrame);
+
+    MR_pneg_next = saved_state->MR_ss_pneg_next;
+    MR_table_copy_structs(MR_pneg_stack,
+        saved_state->MR_ss_pneg_stack_saved_block,
+        saved_state->MR_ss_pneg_next, MR_PNegStackFrame);
+
+  #ifdef MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("\n%s restores %s stacks\n", who, what);
+        print_saved_state(stdout, saved_state);
+    }
+
+    if (MR_tablestackdebug) {
+        MR_dump_nondet_stack_from_layout(stdout, MR_maxfr, NULL,
+            MR_sp, MR_curfr);
+    }
+  #endif /* MR_TABLE_DEBUG */
+
+    MR_save_transient_registers();
+}
+
+/*
+** The saved state of a consumer for a subgoal (say subgoal A) includes
+** the stack segments between the tops of the stack at the time that
+** A's generator was entered and the time that A's consumer was entered.
+** When A becomes a follower of another subgoal B, the responsibility for
+** scheduling A's consumers passes to B's generator. Since by definition
+** B's nondet stack frame is lower in the stack than A's generator's,
+** we need to extend the stack segments of A's consumers to also include
+** the parts of the stacks between the generator of B and the generator of A.
+*/
+
+static void
+extend_consumer_stacks(MR_Subgoal *leader, MR_Consumer *consumer)
+{
+    MR_Word         *arena_block;
+    MR_Word         *arena_start;
+    MR_Word         arena_size;
+    MR_Word         extension_size;
+    MR_Word         *new_common_ancestor_fr;
+    MR_Word         *saved_fr;
+    MR_Word         *real_fr;
+    MR_Word         frame_size;
+    MR_Word         offset;
+    MR_SavedState   *cons_saved_state;
+
+    cons_saved_state = &consumer->MR_cns_saved_state;
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tablestackdebug) {
+        printf("\nextending saved consumer stacks\n");
+        print_saved_state(stdout, cons_saved_state);
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    new_common_ancestor_fr = nearest_common_ancestor(
+        cons_saved_state->MR_ss_common_ancestor_fr,
+        leader->MR_sg_generator_fr);
+    cons_saved_state->MR_ss_common_ancestor_fr = new_common_ancestor_fr;
+
+    arena_start = MR_table_detfr_slot(leader->MR_sg_generator_fr) + 1;
+    extension_size = cons_saved_state->MR_ss_det_stack_real_start
+        - arena_start;
+    arena_size  = extension_size
+        + cons_saved_state->MR_ss_det_stack_block_size;
+
+#if 0
+    if (arena_size != 0) {
+        assert(arena_start + arena_size == cons_saved_state->MR_ss_s_p - 1);
+    }
+#endif
+
+    arena_block = MR_table_allocate_words(arena_size);
+
+    MR_table_copy_words(arena_block, arena_start, extension_size);
+    MR_table_copy_words(arena_block + extension_size,
+        cons_saved_state->MR_ss_det_stack_saved_block,
+        cons_saved_state->MR_ss_det_stack_block_size);
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("extending det stack of consumer %s for %s\n",
+            MR_consumer_addr_name(consumer), MR_subgoal_addr_name(leader));
+        printf("start: old %p, new %p\n",
+            cons_saved_state->MR_ss_det_stack_real_start, arena_start);
+        printf("size:  old %d, new %d\n",
+            cons_saved_state->MR_ss_det_stack_block_size, arena_size);
+        printf("block: old %p, new %p\n",
+            cons_saved_state->MR_ss_det_stack_saved_block, arena_block);
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    cons_saved_state->MR_ss_det_stack_saved_block = arena_block;
+    cons_saved_state->MR_ss_det_stack_block_size = arena_size;
+    cons_saved_state->MR_ss_det_stack_real_start = arena_start;
+
+    arena_start = leader->MR_sg_generator_fr + 1;
+    extension_size = cons_saved_state->MR_ss_non_stack_real_start
+        - arena_start;
+    arena_size  = extension_size
+        + cons_saved_state->MR_ss_non_stack_block_size;
+
+#if 0
+    assert(arena_start + arena_size == cons_saved_state->MR_max_fr);
+#endif
+
+    arena_block = MR_table_allocate_words(arena_size);
+
+    MR_table_copy_words(arena_block, arena_start, extension_size);
+    MR_table_copy_words(arena_block + extension_size,
+        cons_saved_state->MR_ss_non_stack_saved_block,
+        cons_saved_state->MR_ss_non_stack_block_size);
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("extending non stack of suspension %s for %s\n",
+            MR_consumer_addr_name(consumer), MR_subgoal_addr_name(leader));
+        printf("start: old %p, new %p\n",
+            cons_saved_state->MR_ss_non_stack_real_start, arena_start);
+        printf("size:  old %d, new %d\n",
+            cons_saved_state->MR_ss_non_stack_block_size, arena_size);
+        printf("block: old %p, new %p\n",
+            cons_saved_state->MR_ss_non_stack_saved_block, arena_block);
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    cons_saved_state->MR_ss_non_stack_saved_block = arena_block;
+    cons_saved_state->MR_ss_non_stack_block_size = arena_size;
+    cons_saved_state->MR_ss_non_stack_real_start = arena_start;
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tablestackdebug) {
+        printf("\nbefore pickling nondet stack\n");
+        print_saved_state(stdout, cons_saved_state);
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    saved_fr = cons_saved_state->MR_ss_non_stack_saved_block +
+        cons_saved_state->MR_ss_non_stack_block_size - 1;
+    real_fr = cons_saved_state->MR_ss_non_stack_real_start +
+        cons_saved_state->MR_ss_non_stack_block_size - 1;
+    while (saved_fr > cons_saved_state->MR_ss_non_stack_saved_block) {
+        frame_size = real_fr - MR_prevfr_slot(saved_fr);
+
+        if (saved_fr - frame_size >
+            cons_saved_state->MR_ss_non_stack_saved_block)
+        {
+            *MR_redoip_addr(saved_fr) = (MR_Word) MR_ENTRY(MR_do_fail);
+
+#ifdef  MR_TABLE_DEBUG
+            if (MR_tabledebug) {
+                printf("do_fail to redoip at %p (%d)\n",
+                    MR_redoip_addr(saved_fr),
+                    MR_redoip_addr(saved_fr) -
+                        cons_saved_state->MR_ss_non_stack_saved_block);
+            }
+#endif  /* MR_TABLE_DEBUG */
+        } else {
+            *MR_redoip_addr(saved_fr) = (MR_Word) MR_ENTRY(MR_RESUME_ENTRY);
+#ifdef  MR_TABLE_DEBUG
+            if (MR_tabledebug) {
+                printf("resume to redoip at %p (%d)\n",
+                    MR_redoip_addr(saved_fr),
+                    MR_redoip_addr(saved_fr) -
+                        cons_saved_state->MR_ss_non_stack_saved_block);
+            }
+#endif  /* MR_TABLE_DEBUG */
+        } /*** else cut_stack XXX */
+
+        saved_fr -= frame_size;
+        real_fr -= frame_size;
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tablestackdebug) {
+        printf("\nfinished extending saved consumer stacks\n");
+        print_saved_state(stdout, cons_saved_state);
+    }
+#endif  /* MR_TABLE_DEBUG */
+}
+
+/*
+** When we discover that two subgoals depend on each other, neither can be
+** completed alone. We therefore pass responsibility for completing all
+** the subgoals in an SCC to the subgoal whose nondet stack frame is
+** lowest in the nondet stack.
+*/
+
+static void
+make_subgoal_follow_leader(MR_Subgoal *this_follower, MR_Subgoal *leader)
+{
+    MR_Consumer     *suspension;
+    MR_SubgoalList  sub_follower;
+    MR_ConsumerList suspend_list;
+
+    MR_restore_transient_registers();
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("making %s follow %s\n",
+                MR_subgoal_addr_name(this_follower),
+                MR_subgoal_addr_name(leader));
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    for (sub_follower = this_follower->MR_sg_followers;
+        sub_follower != NULL; sub_follower = sub_follower->MR_sl_next)
+    {
+        for (suspend_list = sub_follower->MR_sl_item->MR_sg_consumer_list;
+            suspend_list != NULL;
+            suspend_list = suspend_list->MR_cl_next)
+        {
+            MR_save_transient_registers();
+            extend_consumer_stacks(leader, suspend_list->MR_cl_item);
+            MR_restore_transient_registers();
+            /* suspend_list->item->leader = leader;      XXX */
+        }
+    }
+
+    /* XXX extend saved state of this_follower */
+
+    this_follower->MR_sg_leader = leader;
+    *(leader->MR_sg_followers_tail) = this_follower->MR_sg_followers;
+    this_follower->MR_sg_followers = NULL;
+
+    MR_save_transient_registers();
+}
+
+static void
+print_saved_state(FILE *fp, MR_SavedState *saved_state)
+{
+    fprintf(fp, "saved state parameters:\n");
+    fprintf(fp, "succip:\t");
+    MR_printlabel(fp, saved_state->MR_ss_succ_ip);
+    fprintf(fp, "sp:\t");
+    MR_print_detstackptr(fp, saved_state->MR_ss_s_p);
+    fprintf(fp, "\ncurfr:\t");
+    MR_print_nondstackptr(fp, saved_state->MR_ss_cur_fr);
+    fprintf(fp, "\nmaxfr:\t");
+    MR_print_nondstackptr(fp, saved_state->MR_ss_max_fr);
+    fprintf(fp, "\n");
+
+    fprintf(fp,
+        "slots saved: %d non, %d det, %d generator, %d cut, %d pneg\n",
+        saved_state->MR_ss_non_stack_block_size,
+        saved_state->MR_ss_det_stack_block_size,
+        saved_state->MR_ss_gen_next,
+        saved_state->MR_ss_cut_next,
+        saved_state->MR_ss_pneg_next);
+
+    if (saved_state->MR_ss_non_stack_block_size > 0) {
+        fprintf(fp, "non region from ");
+        MR_print_nondstackptr(fp, saved_state->MR_ss_non_stack_real_start);
+        fprintf(fp, " to ");
+        MR_print_nondstackptr(fp, saved_state->MR_ss_non_stack_real_start +
+            saved_state->MR_ss_non_stack_block_size - 1);
+        fprintf(fp, " (both inclusive)\n");
+    }
+
+  #ifdef MR_TABLE_SEGMENT_DEBUG
+    if (saved_state->MR_ss_non_stack_block_size > 0) {
+        fprintf(fp, "stored at %p to %p (both inclusive)\n",
+            saved_state->MR_ss_non_stack_saved_block,
+            saved_state->MR_ss_non_stack_saved_block +
+                saved_state->MR_ss_non_stack_block_size - 1);
+
+        fprint_stack_segment(fp, saved_state->MR_ss_non_stack_saved_block,
+            saved_state->MR_ss_non_stack_block_size);
+    }
+  #endif /* MR_TABLE_SEGMENT_DEBUG */
+
+    if (saved_state->MR_ss_det_stack_block_size > 0) {
+        fprintf(fp, "det region from ");
+        MR_print_detstackptr(fp, saved_state->MR_ss_det_stack_real_start);
+        fprintf(fp, " to ");
+        MR_print_detstackptr(fp, saved_state->MR_ss_det_stack_real_start +
+            saved_state->MR_ss_det_stack_block_size - 1);
+        fprintf(fp, " (both inclusive)\n");
+    }
+
+  #ifdef MR_TABLE_SEGMENT_DEBUG
+    if (saved_state->MR_ss_det_stack_block_size > 0) {
+        fprintf(fp, "stored at %p to %p (both inclusive)\n",
+            saved_state->MR_ss_det_stack_saved_block,
+            saved_state->MR_ss_det_stack_saved_block +
+                saved_state->MR_ss_det_stack_block_size - 1);
+
+        print_stack_segment(fp, saved_state->MR_ss_det_stack_saved_block,
+            saved_state->MR_ss_det_stack_block_size);
+    }
+  #endif /* MR_TABLE_SEGMENT_DEBUG */
+
+    MR_print_any_gen_stack(fp, saved_state->MR_ss_gen_next,
+        saved_state->MR_ss_gen_stack_saved_block);
+    MR_print_any_cut_stack(fp, saved_state->MR_ss_cut_next,
+        saved_state->MR_ss_cut_stack_saved_block);
+    MR_print_any_pneg_stack(fp, saved_state->MR_ss_pneg_next,
+        saved_state->MR_ss_pneg_stack_saved_block);
+
+    fprintf(fp, "\n");
+}
+
+static void
+print_stack_segment(FILE *fp, MR_Word *segment, MR_Integer size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        fprintf(fp, "%2d %p: %ld (%lx)\n", i, &segment[i],
+            (long) segment[i], (long) segment[i]);
+    }
+}
+
+#endif  /* MR_USE_MINIMAL_MODEL */
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** This part of the file implements the suspension and and resumption
+** of derivations.
+**
+** We need to define stubs for table_nondet_suspend and table_nondet_resume,
+** even if MR_USE_MINIMAL_MODEL is not enabled, since they are declared as
+** `:- external', and hence for profiling grades the generated code will take
+** their address to store in the label table.
+**
+** We provide three definitions for those two procedures: one for high level
+** code (which is incompatible with minimal model tabling), and two for low
+** level code. The first of the latter two is for grades without minimal model
+** tabling, the second is for grades with minimal model tabling.
+*/
+
+#ifdef MR_HIGHLEVEL_CODE
+
+/* Declare them first, to avoid warnings from gcc -Wmissing-decls */
+void MR_CALL mercury__table_builtin__table_nondet_resume_1_p_0(
+    MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
+    MR_Cont cont, void *cont_env_ptr);
+void MR_CALL mercury__table_builtin__table_nondet_suspend_2_p_0(
+    MR_C_Pointer subgoal_table_node);
+
+void MR_CALL
+mercury__table_builtin__table_nondet_resume_1_p_0(
+    MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
+    MR_Cont cont, void *cont_env_ptr)
+{
+    MR_fatal_error("sorry, not implemented: "
+        "minimal model tabling with --high-level-code");
+}
+
+void MR_CALL
+mercury__table_builtin__table_nondet_suspend_2_p_0(
+    MR_C_Pointer subgoal_table_node)
+{
+    MR_fatal_error("sorry, not implemented: "
+        "minimal model tabling with --high-level-code");
+}
+
+#else   /* ! MR_HIGHLEVEL_CODE */
+
+#ifndef  MR_USE_MINIMAL_MODEL
+
+MR_define_extern_entry(MR_SUSPEND_ENTRY);
+MR_define_extern_entry(MR_RESUME_ENTRY);
+MR_MAKE_PROC_LAYOUT(MR_SUSPEND_ENTRY,
+    MR_DETISM_NON, 0, MR_LONG_LVAL_TYPE_UNKNOWN,
+    MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
+MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY,
+    MR_DETISM_NON, 0, MR_LONG_LVAL_TYPE_UNKNOWN,
+    MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
+
+MR_BEGIN_MODULE(table_nondet_suspend_resume_module)
+    MR_init_entry_sl(MR_SUSPEND_ENTRY);
+    MR_init_entry_sl(MR_RESUME_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_SUSPEND_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_RESUME_ENTRY);
+MR_BEGIN_CODE
+
+MR_define_entry(MR_SUSPEND_ENTRY);
+    MR_fatal_error("call to table_nondet_suspend/2 in a grade "
+        "without minimal model tabling");
+
+MR_define_entry(MR_RESUME_ENTRY);
+    MR_fatal_error("call to table_nondet_resume/1 in a grade "
+        "without minimal model tabling");
+MR_END_MODULE
+
+#else   /* MR_USE_MINIMAL_MODEL */
+
+MR_Subgoal      *MR_cur_leader;
+
+MR_declare_entry(MR_do_trace_redo_fail);
+MR_declare_entry(MR_table_nondet_commit);
+
+MR_define_extern_entry(MR_SUSPEND_ENTRY);
+
+MR_define_extern_entry(MR_RESUME_ENTRY);
+MR_declare_label(RESUME_LABEL(ChangeLoop));
+MR_declare_label(RESUME_LABEL(ReachedFixpoint));
+MR_declare_label(RESUME_LABEL(LoopOverSubgoals));
+MR_declare_label(RESUME_LABEL(LoopOverSuspensions));
+MR_declare_label(RESUME_LABEL(ReturnAnswer));
+MR_declare_label(RESUME_LABEL(RedoPoint));
+MR_declare_label(RESUME_LABEL(RestartPoint));
+
+MR_define_extern_entry(MR_table_nondet_commit);
+
+MR_MAKE_PROC_LAYOUT(MR_SUSPEND_ENTRY,
+    MR_DETISM_NON, 0, MR_LONG_LVAL_TYPE_UNKNOWN,
+    MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
+
+MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY,
+    MR_DETISM_NON, 0, MR_LONG_LVAL_TYPE_UNKNOWN,
+    MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(ChangeLoop), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(ReachedFixpoint), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(LoopOverSubgoals), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(LoopOverSuspensions), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(ReturnAnswer), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(RedoPoint), MR_RESUME_ENTRY);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    RESUME_LABEL(RestartPoint), MR_RESUME_ENTRY);
+
+MR_BEGIN_MODULE(table_nondet_suspend_resume_module)
+    MR_init_entry_sl(MR_SUSPEND_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_SUSPEND_ENTRY);
+
+    MR_init_entry_sl(MR_RESUME_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_RESUME_ENTRY);
+    MR_init_label_sl(RESUME_LABEL(ChangeLoop));
+    MR_init_label_sl(RESUME_LABEL(ReachedFixpoint));
+    MR_init_label_sl(RESUME_LABEL(LoopOverSubgoals));
+    MR_init_label_sl(RESUME_LABEL(LoopOverSuspensions));
+    MR_init_label_sl(RESUME_LABEL(ReturnAnswer));
+    MR_init_label_sl(RESUME_LABEL(RedoPoint));
+    MR_init_label_sl(RESUME_LABEL(RestartPoint));
+
+    MR_init_entry_an(MR_table_nondet_commit);
+MR_BEGIN_CODE
+
+MR_define_entry(MR_SUSPEND_ENTRY);
+    /*
+    ** The suspend procedure saves the state of the Mercury runtime so that
+    ** it may be used in the table_nondet_resume procedure below to return
+    ** answers through this saved state. The procedure table_nondet_suspend is
+    ** declared as nondet but the code below is obviously of detism failure;
+    ** the reason for this is quite simple. Normally when a nondet proc is
+    ** called it will first return all of its answers and then fail. In the
+    ** case of calls to this procedure this is reversed: first the call will
+    ** fail then later on, when the answers are found, answers will be
+    ** returned. It is also important to note that the answers are returned
+    ** not from the procedure that was originally called (table_nondet_suspend)
+    ** but from the procedure table_nondet_resume. So essentially what is
+    ** below is the code to do the initial fail; the code to return the
+    ** answers is in table_nondet_resume.
+    */
+
+{
+    MR_TrieNode     table;
+    MR_Subgoal      *subgoal;
+    MR_Consumer     *consumer;
+    MR_ConsumerList listnode;
+    MR_Integer      cur_gen;
+    MR_Integer      cur_cut;
+    MR_Integer      cur_pneg;
+    MR_Word         *fr;
+    MR_Word         *prev_fr;
+    MR_Word         *stop_addr;
+    MR_Word         offset;
+    MR_Word         *clobber_addr;
+
+    /*
+    ** This frame is not used in table_nondet_suspend, but it is copied
+    ** to the suspend list as part of the saved nondet stack fragment,
+    ** and it *will* be used when table_nondet_resume copies back the
+    ** nondet stack fragment. The framevar slot is for use by
+    ** table_nondet_resume.
+    */
+    MR_mkframe(MR_STRINGIFY(MR_SUSPEND_ENTRY), 1, MR_ENTRY(MR_do_fail));
+
+    table = (MR_TrieNode) MR_r1;
+    subgoal = table->MR_subgoal;
+    MR_register_suspension(subgoal);
+    consumer = MR_table_allocate_struct(MR_Consumer);
+    consumer->MR_cns_remaining_answer_list_ptr = &subgoal->MR_sg_answer_list;
+
+#ifdef  MR_TABLE_DEBUG
+    consumer->MR_cns_subgoal = subgoal;
+    MR_enter_consumer_debug(consumer);
+
+    if (MR_tabledebug) {
+        printf("setting up consumer %s\n", MR_consumer_addr_name(consumer));
+    }
+#endif
+
+    MR_save_transient_registers();
+    save_state(&(consumer->MR_cns_saved_state), subgoal->MR_sg_generator_fr,
+        "suspension", "consumer");
+    MR_restore_transient_registers();
+
+    cur_gen = MR_gen_next - 1;
+    cur_cut = MR_cut_next - 1;
+    cur_pneg = MR_pneg_next - 1;
+    stop_addr = consumer->MR_cns_saved_state.MR_ss_non_stack_real_start;
+    for (fr = MR_maxfr; fr > stop_addr; fr = MR_prevfr_slot(fr)) {
+        offset = MR_redoip_addr(fr) -
+            consumer->MR_cns_saved_state.MR_ss_non_stack_real_start;
+        clobber_addr = consumer->MR_cns_saved_state.MR_ss_non_stack_saved_block
+            + offset;
+#if 0
+        if (MR_tablestackdebug) {
+            printf("redoip addr ");
+            MR_printnondstackptr(MR_redoip_addr(fr));
+            printf(", offset %d from start, ", offset);
+            printf("saved copy at %p\n", clobber_addr);
+        }
+#endif
+
+        if (fr == MR_gen_stack[cur_gen].MR_generator_frame) {
+            if (MR_gen_stack[cur_gen].MR_generator_table->MR_subgoal
+                == subgoal)
+            {
+                /*
+                ** This is the nondet stack frame of the
+                ** generator corresponding to this consumer.
+                */
+
+                *clobber_addr = (MR_Word) MR_ENTRY(MR_RESUME_ENTRY);
+  #ifdef  MR_TABLE_DEBUG
+                if (MR_tablestackdebug) {
+                    printf("completing redoip of frame at ");
+                    MR_printnondstackptr(fr);
+                    printf(" (in saved copy)\n");
+                }
+  #endif    /* MR_TABLE_DEBUG */
+
+                consumer->MR_cns_saved_state.MR_ss_gen_next = cur_gen + 1;
+  #ifdef  MR_TABLE_DEBUG
+                if (MR_tabledebug) {
+                    printf("saved gen_next set to %d\n", cur_gen + 1);
+                }
+  #endif    /* MR_TABLE_DEBUG */
+            } else {
+                /*
+                ** This is the nondet stack frame of some other generator.
+                */
+
+  #if 0
+                assert(MR_prevfr_slot(fr) != (stop_addr - 1));
+  #endif
+
+                *clobber_addr = (MR_Word) MR_ENTRY(MR_do_fail);
+  #ifdef  MR_TABLE_DEBUG
+                if (MR_tablestackdebug) {
+                    printf("clobbering redoip of frame at ");
+                    MR_printnondstackptr(fr);
+                    printf(" (in saved copy)\n");
+                }
+  #endif    /* MR_TABLE_DEBUG */
+
+                MR_save_transient_registers();
+                make_subgoal_follow_leader(MR_gen_stack[cur_gen].
+                    MR_generator_table->MR_subgoal, subgoal);
+                MR_restore_transient_registers();
+            }
+
+            cur_gen--;
+            /* XXX can we be at a generator AND a cut? */
+        } else if (cur_cut > 0 && fr == MR_cut_stack[cur_cut].MR_cut_frame) {
+            *clobber_addr = (MR_Word) MR_ENTRY(MR_table_nondet_commit);
+  #ifdef  MR_TABLE_DEBUG
+            if (MR_tablestackdebug) {
+                printf("committing redoip of frame at ");
+                MR_printnondstackptr(fr);
+                printf(" (in saved copy)\n");
+            }
+  #endif    /* MR_TABLE_DEBUG */
+
+            cur_cut--;
+        } else {
+            *clobber_addr = (MR_Word) MR_ENTRY(MR_do_fail);
+  #ifdef  MR_TABLE_DEBUG
+            if (MR_tablestackdebug) {
+                printf("clobbering redoip of frame at ");
+                MR_printnondstackptr(fr);
+                printf(" (in saved copy)\n");
+            }
+  #endif    /* MR_TABLE_DEBUG */
+        }
+    }
+
+  #ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("adding suspension node %s to table %s",
+                MR_consumer_addr_name(consumer),
+                MR_subgoal_addr_name(subgoal));
+        printf("\n\tat slot %p\n", subgoal->MR_sg_consumer_list_tail);
+    }
+  #endif    /* MR_TABLE_DEBUG */
+
+    assert(*(subgoal->MR_sg_consumer_list_tail) == NULL);
+    listnode = MR_table_allocate_struct(MR_ConsumerListNode);
+    *(subgoal->MR_sg_consumer_list_tail) = listnode;
+    subgoal->MR_sg_consumer_list_tail = &(listnode->MR_cl_next);
+    listnode->MR_cl_item = consumer;
+    listnode->MR_cl_next = NULL;
+}
+    MR_fail();
+
+MR_define_entry(MR_RESUME_ENTRY);
+
+    /*
+    ** The resume procedure restores answers to suspended consumers.
+    ** It works by restoring the consumer state saved by the consumer's call
+    ** to table_nondet_suspend. By restoring such states and then returning
+    ** answers, table_nondet_resume is essentially returning answers out of
+    ** the call to table_nondet_suspend, not out of the call to
+    ** table_nondet_resume.
+    **
+    ** The code is arranged as a three level iteration to a fixpoint. The
+    ** three levels are: iterating over all subgoals in a connected component,
+    ** iterating over all consumers of each of those subgoals, and iterating
+    ** over all the answers to be returned to each of those consumers.
+    ** Note that returning an answer could lead to further answers for
+    ** any of the subgoals in the connected component; it can even lead
+    ** to the expansion of the component (i.e. the addition of more subgoals
+    ** to it).
+    */
+
+    MR_cur_leader = MR_top_generator_table();
+
+    if (MR_cur_leader->MR_sg_leader != NULL) {
+        /*
+        ** The predicate that called table_nondet_resume is not the leader
+        ** of its component. We will leave all answers to be returned
+        ** by the leader.
+        */
+
+  #ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("non-leader table_nondet_resume fails\n");
+        }
+  #endif  /* MR_TABLE_DEBUG */
+
+        (void) MR_pop_generator();
+        MR_redo();
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("table_nondet_resume enter: current leader is %s\n",
+            MR_subgoal_addr_name(MR_cur_leader));
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    if (MR_cur_leader->MR_sg_resume_info != NULL) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("using existing resume info %p\n",
+                MR_cur_leader->MR_sg_resume_info);
+        }
+#endif  /* MR_TABLE_DEBUG */
+    } else {
+        MR_cur_leader->MR_sg_resume_info = MR_TABLE_NEW(MR_ResumeInfo);
+        MR_cur_leader->MR_sg_resume_info->MR_ri_saved_succip = MR_succip;/*NEW*/
+
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("resume info succip ");
+            MR_print_label(stdout, MR_succip);
+        }
+#endif  /* MR_TABLE_DEBUG */
+
+        /*
+        ** we should compute, for all followers, the common ancestor
+        ** of the follower and this generator, and save to the deepest
+        ** common ancestor XXX
+        **
+        ** special case the situation where there are no answers
+        ** we have not yet returned to consumers
+        */
+
+        MR_save_transient_registers();
+        save_state(&(MR_cur_leader->MR_sg_resume_info->MR_ri_leader_state),
+            MR_cur_leader->MR_sg_generator_fr, "resumption", "generator");
+        MR_restore_transient_registers();
+
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("creating new resume info %p\n",
+                MR_cur_leader->MR_sg_resume_info);
+        }
+#endif  /* MR_TABLE_DEBUG */
+    }
+
+    /* XXX try doing the test at the bottom */
+    MR_cur_leader->MR_sg_resume_info->MR_ri_changed = MR_TRUE;
+
+MR_define_label(RESUME_LABEL(ChangeLoop));
+{
+    MR_ResumeInfo   *resume_info;
+    
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+    if (resume_info->MR_ri_changed) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("changed flag set\n");
+        }
+#endif  /* MR_TABLE_DEBUG */
+    } else {
+        MR_SubgoalList  table_list;
+
+        /* XXX make sure subgoal_list is initialized early */
+        for (table_list = resume_info->MR_ri_subgoal_list;
+            table_list != NULL;
+            table_list = table_list->MR_sl_next)
+        {
+            if (table_list->MR_sl_item->MR_sg_num_committed_ans
+                != table_list->MR_sl_item->MR_sg_num_ans)
+            {
+                resume_info->MR_ri_changed = MR_TRUE;
+#ifdef  MR_TABLE_DEBUG
+                if (MR_tabledebug) {
+                    printf("table %s has new answers\n",
+                        MR_subgoal_addr_name(table_list->MR_sl_item));
+                }
+#endif  /* MR_TABLE_DEBUG */
+            }
+        }
+    }
+
+    if (! resume_info->MR_ri_changed) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("no more changes\n");
+        }
+#endif  /* MR_TABLE_DEBUG */
+
+        MR_GOTO_LABEL(RESUME_LABEL(ReachedFixpoint));
+    }
+
+    resume_info->MR_ri_subgoal_list = MR_cur_leader->MR_sg_followers;
+    if (resume_info->MR_ri_subgoal_list == NULL) {
+        resume_info->MR_ri_changed = MR_FALSE; /* XXX NEW */
+    }
+}
+
+    /* For each of the subgoals on our list of followers */
+MR_define_label(RESUME_LABEL(LoopOverSubgoals));
+{
+    MR_ResumeInfo   *resume_info;
+    
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+    if (resume_info->MR_ri_subgoal_list == NULL) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("no more subgoals in the followers list\n");
+        }
+#endif  /* MR_TABLE_DEBUG */
+
+        MR_GOTO_LABEL(RESUME_LABEL(ChangeLoop));
+    }
+
+    resume_info->MR_ri_cur_subgoal =
+        resume_info->MR_ri_subgoal_list->MR_sl_item;
+    resume_info->MR_ri_subgoal_list =
+        resume_info->MR_ri_subgoal_list->MR_sl_next;
+
+    resume_info->MR_ri_consumer_list =
+        resume_info->MR_ri_cur_subgoal->MR_sg_consumer_list;
+
+    resume_info->MR_ri_changed = MR_FALSE;
+    resume_info->MR_ri_cur_subgoal->MR_sg_num_committed_ans =
+        resume_info->MR_ri_cur_subgoal->MR_sg_num_ans;
+}
+
+    /* For each of the suspended nodes for cur_subgoal */
+MR_define_label(RESUME_LABEL(LoopOverSuspensions));
+{
+    MR_ResumeInfo   *resume_info;
+    
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+    if (resume_info->MR_ri_consumer_list == NULL) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("no more suspensions for current subgoal\n");
+        }
+#endif  /* MR_TABLE_DEBUG */
+        MR_GOTO_LABEL(RESUME_LABEL(LoopOverSubgoals));
+    }
+
+    resume_info->MR_ri_cur_consumer =
+        resume_info->MR_ri_consumer_list->MR_cl_item;
+    resume_info->MR_ri_consumer_list =
+        resume_info->MR_ri_consumer_list->MR_cl_next;
+
+    resume_info->MR_ri_cur_consumer_answer_list =
+        *(resume_info->MR_ri_cur_consumer->MR_cns_remaining_answer_list_ptr);
+
+    if (resume_info->MR_ri_cur_consumer_answer_list == NULL) {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("no first answer for this suspension\n");
+        }
+#endif  /* MR_TABLE_DEBUG */
+        MR_GOTO_LABEL(RESUME_LABEL(LoopOverSuspensions));
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("resuming consumer %s from table %s\n",
+            MR_consumer_addr_name(resume_info->MR_ri_cur_consumer),
+            MR_subgoal_addr_name(resume_info->MR_ri_cur_subgoal));
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    MR_save_transient_registers();
+    restore_state(&(resume_info->MR_ri_cur_consumer->MR_cns_saved_state),
+        "resumption", "consumer");
+    MR_restore_transient_registers();
+
+    /* check that there is room for exactly one framevar */
+    assert((MR_maxfr - MR_prevfr_slot(MR_maxfr)) ==
+        (MR_NONDET_FIXED_SIZE + 1));
+
+    MR_gen_next = resume_info->MR_ri_leader_state.MR_ss_gen_next;
+    MR_redoip_slot(MR_maxfr) = MR_LABEL(RESUME_LABEL(RedoPoint));
+    MR_redofr_slot(MR_maxfr) = MR_maxfr;
+    MR_based_framevar(MR_maxfr, 1) = (MR_Word) MR_cur_leader;
+}
+
+MR_define_label(RESUME_LABEL(ReturnAnswer));
+{
+    MR_ResumeInfo   *resume_info;
+    
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+    /*
+    ** Return the next answer in MR_cur_leader->MR_sg_resume_info->
+    ** cur_consumer_answer_list to the current consumer. Since we have
+    ** already restored the context of the suspended consumer before
+    ** we returned the first answer, we don't need to restore it again,
+    ** since will not have changed in the meantime.
+    */
+
+    MR_r1 = (MR_Word)
+        &resume_info->MR_ri_cur_consumer_answer_list->MR_aln_answer_data;
+    resume_info->MR_ri_cur_consumer->MR_cns_remaining_answer_list_ptr =
+        &(resume_info->MR_ri_cur_consumer_answer_list->MR_aln_next_answer);
+    resume_info->MR_ri_cur_consumer_answer_list =
+        resume_info->MR_ri_cur_consumer_answer_list->MR_aln_next_answer;
+
+    /*
+    ** Return the answer. Since we just restored the state of the
+    ** computation that existed when suspend was called, the code
+    ** that we return to is the code following the call to suspend.
+    */
+    MR_succeed();
+}
+
+MR_define_label(RESUME_LABEL(RedoPoint));
+    MR_update_prof_current_proc(MR_LABEL(MR_RESUME_ENTRY));
+
+    /*
+    ** This is where the current consumer suspension will go on
+    ** backtracking when it wants the next solution. If there is a solution
+    ** we haven't returned to this consumer yet, we do so, otherwise we
+    ** remember how many answers we have returned to this consumer so far
+    ** and move on to the next suspended consumer of the current subgoal.
+    */
+
+    MR_cur_leader = (MR_Subgoal *) MR_based_framevar(MR_maxfr, 1);
+
+MR_define_label(RESUME_LABEL(RestartPoint));
+{
+    MR_ResumeInfo   *resume_info;
+    MR_Subgoal      *cur_subgoal;
+    
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("cur_consumer_answer_list: %p\n",
+            resume_info->MR_ri_cur_consumer_answer_list);
+        printf("*cur_consumer->remaining_answer_list_ptr: %p\n",
+            *(resume_info->MR_ri_cur_consumer->
+                MR_cns_remaining_answer_list_ptr));
+    }
+#endif
+
+    if (resume_info->MR_ri_cur_consumer_answer_list != NULL) {
+        MR_GOTO_LABEL(RESUME_LABEL(ReturnAnswer));
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("no more unreturned answers for this suspension\n");
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    cur_subgoal = resume_info->MR_ri_cur_subgoal;
+    if (cur_subgoal->MR_sg_num_committed_ans != cur_subgoal->MR_sg_num_ans) {
+        resume_info->MR_ri_changed = MR_TRUE;
+    }
+
+    MR_GOTO_LABEL(RESUME_LABEL(LoopOverSuspensions));
+}
+MR_define_label(RESUME_LABEL(ReachedFixpoint));
+{
+    MR_SubgoalList  table_list;
+    MR_ResumeInfo   *resume_info;
+
+    for (table_list = MR_cur_leader->MR_sg_followers;
+        table_list != NULL;
+        table_list = table_list->MR_sl_next)
+    {
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("marking table %s complete\n",
+                MR_subgoal_addr_name(table_list->MR_sl_item));
+        }
+#endif
+
+        table_list->MR_sl_item->MR_sg_status = MR_SUBGOAL_COMPLETE;
+        table_list->MR_sl_item->MR_sg_num_committed_ans = -1;
+    }
+
+    resume_info = MR_cur_leader->MR_sg_resume_info;
+
+    /* Restore the state we had when table_nondet_resume was called */
+    MR_save_transient_registers();
+    restore_state(&(resume_info->MR_ri_leader_state),
+        "resumption", "generator");
+    MR_restore_transient_registers();
+
+    /* XXX this will go code that does fail() */
+    MR_succip = resume_info->MR_ri_saved_succip;
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("using resume info succip ");
+        MR_print_label(stdout, MR_succip);
+    }
+#endif  /* MR_TABLE_DEBUG */
+
+    /* YYY OLD */
+    /* we should free the old resume_info structure */
+    MR_cur_leader->MR_sg_resume_info = NULL;
+
+    /* YYY OLD */
+    /* We are done with this generator */
+    (void) MR_pop_generator();
+
+    MR_proceed();
+}
+
+MR_define_entry(MR_table_nondet_commit);
+    MR_commit_cut();
+    MR_fail();
+
+MR_END_MODULE
+
+#endif /* MR_USE_MINIMAL_MODEL */
+#endif /* MR_HIGHLEVEL_CODE */
+
+/* Ensure that the initialization code for the above modules gets to run. */
+/*
+INIT mercury_sys_init_table_modules
+*/
+
+MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_nondet_suspend_resume_module;
+
+/* forward declarations to suppress gcc -Wmissing-decl warnings */
+void mercury_sys_init_table_modules_init(void);
+void mercury_sys_init_table_modules_init_type_tables(void);
+#ifdef  MR_DEEP_PROFILING
+void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp);
+#endif
+
+void mercury_sys_init_table_modules_init(void)
+{
+#ifndef MR_HIGHLEVEL_CODE
+    table_nondet_suspend_resume_module();
+#endif  /* MR_HIGHLEVEL_CODE */
+}
+
+void mercury_sys_init_table_modules_init_type_tables(void)
+{
+    /* no types to register */
+}
+
+#ifdef  MR_DEEP_PROFILING
+void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp)
+{
+    /* no proc_statics to write out */
+}
+#endif
Index: runtime/mercury_minimal_model.h
===================================================================
RCS file: runtime/mercury_minimal_model.h
diff -N runtime/mercury_minimal_model.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_minimal_model.h	13 Mar 2003 06:46:09 -0000
@@ -0,0 +1,225 @@
+/*
+** Copyright (C) 2003 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** mercury_minimal_model.h - definitions of some basic stuff used for tabling.
+** For tabling code, the Mercury compiler (compiler/table_gen.m) generates
+** references to special procedures defined in library/table_builtin.m.
+** The types and macros defined here are used by the procedures defined in
+** library/table_builtin.m.
+*/
+
+#ifndef	MERCURY_MINIMAL_MODEL_H
+#define	MERCURY_MINIMAL_MODEL_H
+
+#include "mercury_imp.h"
+#include "mercury_tabling.h"
+#include "mercury_reg_workarounds.h"
+#include "mercury_goto.h"		/* for MR_declare_entry */
+
+struct MR_AnswerListNode_Struct {
+	MR_Integer	MR_aln_answer_num;
+	MR_TableNode	MR_aln_answer_data;
+				/* always uses the MR_answerblock member */
+	MR_AnswerList	MR_aln_next_answer;
+};
+
+/*
+** The saved state of a generator or a consumer. While consumers get
+** suspended while they are waiting for generators to produce more solutions,
+** generators need their state saved when they restore the state of a consumer
+** to consume a new solution.
+**
+** The saved state contains copies of
+**
+** - several virtual machine registers:
+**   MR_succip, MR_sp, MR_curfr and MR_maxfr
+**
+** - segments of the nondet and det stacks:
+**   the parts that cannot possibly change between the times of saving
+**   and restoring the saved state are not saved.
+**
+**   The segments are described by three fields each. The *_real_start
+**   field gives the address of the first word in the real stack
+**   that is part of the saved segment, the *_block_size field
+**   gives the size of the saved segment in words, and the *_saved_block
+**   field points to the area of memory containing the saved segment.
+**
+** - the entire generator stack and the entire cut stack:
+**   they are usually so small, it is faster to save them all
+**   than to figure out which parts need saving.
+**
+**   Each stack is described by its size in words and a pointer to
+**   an area of memory containing the entire saved stack.
+*/
+
+typedef struct {
+	MR_Code			*MR_ss_succ_ip;
+	MR_Word			*MR_ss_s_p;
+	MR_Word			*MR_ss_cur_fr;
+	MR_Word			*MR_ss_max_fr;
+	MR_Word			*MR_ss_common_ancestor_fr;
+
+	MR_Word			*MR_ss_non_stack_real_start;
+	MR_Word			MR_ss_non_stack_block_size;
+	MR_Word			*MR_ss_non_stack_saved_block;
+
+	MR_Word			*MR_ss_det_stack_real_start;
+	MR_Word			MR_ss_det_stack_block_size;
+	MR_Word			*MR_ss_det_stack_saved_block;
+
+	MR_Integer		MR_ss_gen_next;
+	MR_GenStackFrame	*MR_ss_gen_stack_saved_block;
+
+	MR_Integer		MR_ss_cut_next;
+	MR_CutStackFrame	*MR_ss_cut_stack_saved_block;
+
+	MR_Integer		MR_ss_pneg_next;
+	MR_PNegStackFrame	*MR_ss_pneg_stack_saved_block;
+} MR_SavedState;
+
+/* The state of a consumer subgoal */
+typedef struct {
+	MR_SavedState		MR_cns_saved_state;
+	MR_AnswerList		*MR_cns_remaining_answer_list_ptr;
+#ifdef	MR_TABLE_DEBUG
+	MR_Subgoal		*MR_cns_subgoal;
+#endif
+} MR_Consumer;
+
+struct MR_ConsumerListNode_Struct {
+	MR_Consumer		*MR_cl_item;
+	MR_ConsumerList		MR_cl_next;
+};
+
+/*
+** The following structure is used to hold the state and variables used in 
+** the table_resume procedure.
+*/
+
+typedef struct {
+	MR_SavedState		MR_ri_leader_state;
+	MR_SubgoalList		MR_ri_subgoal_list;
+	MR_Subgoal		*MR_ri_cur_subgoal;
+	MR_ConsumerList		MR_ri_consumer_list; /* for the cur subgoal */
+	MR_Consumer		*MR_ri_cur_consumer;
+	MR_AnswerList		MR_ri_cur_consumer_answer_list;
+	MR_bool			MR_ri_changed;
+	MR_Code			*MR_ri_saved_succip;
+} MR_ResumeInfo;
+
+struct MR_SubgoalListNode_Struct {
+	MR_Subgoal		*MR_sl_item;
+	MR_SubgoalList		MR_sl_next;
+};
+
+/*
+** The subgoal structure represents a subgoal, i.e. a call to a minimal model
+** predicate with a given set of input arguments.
+**
+** The MR_sg_status obviously gives the current status of the subgoal.
+**
+** The MR_sg_leader field points to the leader of the clique of subgoals this
+** subgoal is a member of, if the leader is not the subgoal itself. If the
+** subgoal is the leader of its clique, then this field will be NULL.
+**
+** The MR_sg_followers field lists all the subgoals that follow this one.
+** Each subgoal occurs in its own followers list.
+**
+** The MR_sg_followers_tail field points to the NULL pointer at the tail of
+** the MR_sg_followers list, to allow us to add new elements at the tail in
+** constant time.
+**
+** The MR_sg_resume_info field, when non-NULL, points to a data structure
+** containing the local variables of the algorithm executed by the builtin
+** predicate table_nondet_resume. The execution of that algorithm invokes
+** general Mercury code and moves stack segments around many times, which
+** is why its local variables cannot be stored in a stack frame.
+**
+** The MR_sg_answer_table field points to the trie of answers returned for
+** this subgoal so far (to enable efficient checks for duplicate answers).
+**
+** The MR_sg_answer_list field also contains the answers so far, in a list.
+** The answers will be returned to consumers in the order given by this list.
+** The MR_sg_answer_list_tail field points to the NULL pointer at the tail
+** of this list, to allow us to add new elements to the list at the tail in
+** constant time.
+**
+** The MR_sg_num_ans field gives the number of answers computed so far, i.e.
+** the number of answers in MR_sg_answer_table and MR_sg_answer_list.
+** The MR_sg_num_committed_ans field gives the number of answers that the
+** leader is committed to returning to all consumers.
+**
+** The MR_sg_consumer_list gives the list of consumer goals, with the field
+** MR_sg_consumer_list_tail allowing fast appending to the end.
+**
+** The MR_sg_generator_fr points to the generator's nondet stack frame.
+*/
+
+struct MR_Subgoal_Struct {
+	MR_SubgoalStatus	MR_sg_status;
+	MR_Subgoal		*MR_sg_leader;
+	MR_SubgoalList		MR_sg_followers;
+	MR_SubgoalList		*MR_sg_followers_tail;
+	MR_ResumeInfo		*MR_sg_resume_info;
+	MR_Word			MR_sg_answer_table;
+	MR_Integer		MR_sg_num_ans;
+	MR_Integer		MR_sg_num_committed_ans;
+	MR_AnswerList		MR_sg_answer_list;
+	MR_AnswerList		*MR_sg_answer_list_tail;
+	MR_ConsumerList		MR_sg_consumer_list;
+	MR_ConsumerList		*MR_sg_consumer_list_tail;
+	MR_Word			*MR_sg_generator_fr;
+#ifdef	MR_TABLE_DEBUG
+	MR_Proc_Layout		*MR_sg_proc_layout;
+#endif	MR_TABLE_DEBUG
+};
+
+/*---------------------------------------------------------------------------*/
+
+extern	MR_Proc_Layout	*MR_subgoal_debug_cur_proc;
+
+typedef struct MR_ConsumerDebug_Struct	MR_ConsumerDebug;
+typedef struct MR_SubgoalDebug_Struct	MR_SubgoalDebug;
+
+extern	void		MR_enter_consumer_debug(MR_Consumer *consumer);
+extern	MR_ConsumerDebug *MR_lookup_consumer_debug_addr(MR_Consumer *consumer);
+extern	MR_ConsumerDebug *MR_lookup_consumer_debug_num(int consumer_index);
+extern	const char	*MR_consumer_debug_name(MR_ConsumerDebug *consumer_dbg);
+extern	const char	*MR_consumer_addr_name(MR_Consumer *consumer);
+extern	const char	*MR_consumer_num_name(int consumer_index);
+
+extern	void		MR_enter_subgoal_debug(MR_Subgoal *subgoal);
+extern	MR_SubgoalDebug	*MR_lookup_subgoal_debug_addr(MR_Subgoal *subgoal);
+extern	MR_SubgoalDebug	*MR_lookup_subgoal_debug_num(int subgoal_index);
+extern	const char	*MR_subgoal_debug_name(MR_SubgoalDebug *subgoal_debug);
+extern	const char	*MR_subgoal_addr_name(MR_Subgoal *subgoal);
+extern	const char	*MR_subgoal_num_name(int subgoal_index);
+extern	const char	*MR_subgoal_status(MR_SubgoalStatus status);
+
+extern	void		MR_print_subgoal_debug(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_SubgoalDebug *subgoal_debug);
+extern	void		MR_print_subgoal(FILE *fp, const MR_Proc_Layout *proc,
+				MR_Subgoal *subgoal);
+extern	void		MR_print_consumer_debug(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_ConsumerDebug *consumer_debug);
+extern	void		MR_print_consumer(FILE *fp, const MR_Proc_Layout *proc,
+				MR_Consumer *consumer);
+
+
+#ifndef	MR_HIGHLEVEL_CODE
+
+  #define MR_SUSPEND_ENTRY     mercury__table_builtin__table_nondet_suspend_2_0
+  #define MR_RESUME_ENTRY      mercury__table_builtin__table_nondet_resume_1_0
+
+  MR_declare_entry(MR_SUSPEND_ENTRY);
+  MR_declare_entry(MR_RESUME_ENTRY);
+
+#endif	/* !MR_HIGHLEVEL_CODE */
+
+#endif	/* MERCURY_MINIMAL_MODEL_H */
Index: runtime/mercury_regorder.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_regorder.h,v
retrieving revision 1.17
diff -u -b -r1.17 mercury_regorder.h
--- runtime/mercury_regorder.h	23 Nov 2000 02:00:37 -0000	1.17
+++ runtime/mercury_regorder.h	10 Mar 2003 09:22:00 -0000
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1994-1995, 1997-2000 The University of Melbourne.
+** Copyright (C) 1994-1995,1997-2000,2003 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
@@ -115,13 +115,18 @@
 #define MR_gen_next		MR_LVALUE_CAST(MR_Integer,		\
 				MR_count_usage(MR_GEN_NEXT_RN, MR_mr(42)))
 #define MR_gen_stack		MR_LVALUE_CAST(				\
-				struct MR_GeneratorStackFrameStruct *,	\
+				struct MR_GenStackFrameStruct *,	\
 				MR_count_usage(MR_GEN_STACK_RN, MR_mr(43)))
 #define MR_cut_next		MR_LVALUE_CAST(MR_Integer,		\
 				MR_count_usage(MR_CUT_NEXT_RN, MR_mr(44)))
 #define MR_cut_stack		MR_LVALUE_CAST(				\
 				struct MR_CutStackFrameStruct *,	\
 				MR_count_usage(MR_CUT_STACK_RN, MR_mr(45)))
+#define MR_pneg_next		MR_LVALUE_CAST(MR_Integer,		\
+				MR_count_usage(MR_CUT_NEXT_RN, MR_mr(46)))
+#define MR_pneg_stack		MR_LVALUE_CAST(				\
+				struct MR_PNegStackFrameStruct *,	\
+				MR_count_usage(MR_CUT_STACK_RN, MR_mr(47)))
 #define MR_trail_ptr		MR_count_usage(MR_TRAIL_PTR_RN,		\
 				MR_trail_ptr_var)
 #define MR_ticket_counter	MR_count_usage(MR_TICKET_COUNTER_RN,	\
@@ -141,7 +146,7 @@
 #define MR_NUM_SPECIAL_REG	16
 
 /* the maximum MR_mrN number of special registers */
-#define	MR_MAX_SPECIAL_REG_MR	45
+#define	MR_MAX_SPECIAL_REG_MR	47
 
 /*
 ** The MR_saved_foo macros are like MR_foo except that
@@ -170,13 +175,18 @@
 #define MR_saved_gen_next(save_area)	MR_LVALUE_CAST(MR_Integer, \
 						save_area[42])
 #define MR_saved_gen_stack(save_area)	MR_LVALUE_CAST(struct \
-						MR_GeneratorStackFrameStruct *,\
+						MR_GenStackFrameStruct *, \
 						save_area[43])
 #define MR_saved_cut_next(save_area)	MR_LVALUE_CAST(MR_Integer, \
 						save_area[44])
 #define MR_saved_cut_stack(save_area)	MR_LVALUE_CAST(struct \
 						MR_CutStackFrameStruct *, \
 						save_area[45])
+#define MR_saved_pneg_next(save_area)	MR_LVALUE_CAST(MR_Integer, \
+						save_area[46])
+#define MR_saved_pneg_stack(save_area)	MR_LVALUE_CAST(struct \
+						MR_PNegStackFrameStruct *, \
+						save_area[47])
 
 #define MR_VIRTUAL_REG_MAP_BODY	{ \
 	3, \
@@ -303,13 +313,18 @@
 #define MR_gen_next		MR_LVALUE_CAST(MR_Integer,		\
 				MR_count_usage(MR_GEN_NEXT_RN, MR_mr(41)))
 #define MR_gen_stack		MR_LVALUE_CAST(				\
-				struct MR_GeneratorStackFrameStruct *,	\
+				struct MR_GenStackFrameStruct *,	\
 				MR_count_usage(MR_GEN_STACK_RN, MR_mr(42)))
 #define MR_cut_next		MR_LVALUE_CAST(MR_Integer,		\
 				MR_count_usage(MR_CUT_NEXT_RN, MR_mr(43)))
 #define MR_cut_stack		MR_LVALUE_CAST(				\
 				struct MR_CutStackFrameStruct *,	\
 				MR_count_usage(MR_CUT_STACK_RN, MR_mr(44)))
+#define MR_pneg_next		MR_LVALUE_CAST(MR_Integer,		\
+				MR_count_usage(MR_CUT_NEXT_RN, MR_mr(45)))
+#define MR_pneg_stack		MR_LVALUE_CAST(				\
+				struct MR_PNegStackFrameStruct *,	\
+				MR_count_usage(MR_CUT_STACK_RN, MR_mr(46)))
 
 /*
 ** the number of "very special" registers, i.e. special registers that can
@@ -323,7 +338,7 @@
 #define MR_NUM_SPECIAL_REG	15
 
 /* the maximum MR_mrN number of special, non rN registers */
-#define	MR_MAX_SPECIAL_REG_MR	44
+#define	MR_MAX_SPECIAL_REG_MR	46
 
 /*
 ** The MR_saved_foo macros are like MR_foo except that
@@ -352,13 +367,18 @@
 #define MR_saved_gen_stack(save_area)	MR_LVALUE_CAST(MR_Integer, \
 						save_area[41])
 #define MR_saved_gen_next(save_area)	MR_LVALUE_CAST(struct \
-						MR_GeneratorStackFrameStruct *,\
+						MR_GenStackFrameStruct *, \
 						save_area[42])
 #define MR_saved_cut_stack(save_area)	MR_LVALUE_CAST(MR_Integer, \
 						save_area[43])
 #define MR_saved_cut_next(save_area)	MR_LVALUE_CAST(struct \
 						MR_CutStackFrameStruct *,\
 						save_area[44])
+#define MR_saved_pneg_stack(save_area)	MR_LVALUE_CAST(MR_Integer, \
+						save_area[45])
+#define MR_saved_pneg_next(save_area)	MR_LVALUE_CAST(struct \
+						MR_PNegStackFrameStruct *,\
+						save_area[46])
 
 #define MR_VIRTUAL_REG_MAP_BODY	{ \
 	2, \
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.52
diff -u -b -r1.52 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c	17 Jan 2003 05:56:51 -0000	1.52
+++ runtime/mercury_stack_trace.c	14 Mar 2003 04:45:42 -0000
@@ -19,19 +19,26 @@
 #include "mercury_debug.h"
 #include "mercury_array_macros.h"
 #include "mercury_trace_base.h"
+#include "mercury_tabling.h"
 #include <stdio.h>
 
 #if defined(MR_HAVE__SNPRINTF) && ! defined(MR_HAVE_SNPRINTF)
   #define snprintf	_snprintf
 #endif
 
+static  MR_Stack_Walk_Step_Result
+                    MR_stack_walk_succip_layout(MR_Code *success,
+                        const MR_Label_Layout **return_label_layout,
+                        const char **problem_ptr);
+
 #ifndef MR_HIGHLEVEL_CODE
 
 static  const char  *MR_step_over_nondet_frame(FILE *fp,
                         int level_number, MR_Word *fr);
 static  MR_bool     MR_find_matching_branch(MR_Word *fr, int *branch_ptr);
 static  void        MR_record_temp_redoip(MR_Word *fr);
-static  MR_Code     *MR_find_temp_redoip(MR_Word *fr);
+static  MR_bool     MR_nofail_ip(MR_Code *ip);
+static  MR_Code     *MR_find_nofail_temp_redoip(MR_Word *fr);
 static  void        MR_erase_temp_redoip(MR_Word *fr);
 
 #endif  /* !MR_HIGHLEVEL_CODE */
@@ -183,7 +190,6 @@
     MR_Word **stack_trace_sp_ptr, MR_Word **stack_trace_curfr_ptr,
     const char **problem_ptr)
 {
-    MR_Internal             *label;
     MR_Long_Lval            location;
     MR_Long_Lval_Type       type;
     int                     number;
@@ -221,6 +227,16 @@
             *stack_trace_curfr_ptr = MR_succfr_slot(*stack_trace_curfr_ptr);
     }
 
+    return MR_stack_walk_succip_layout(success, return_label_layout,
+        problem_ptr);
+}
+
+static MR_Stack_Walk_Step_Result
+MR_stack_walk_succip_layout(MR_Code *success,
+    const MR_Label_Layout **return_label_layout, const char **problem_ptr)
+{
+    MR_Internal             *label;
+
     if (success == MR_stack_trace_bottom) {
         return MR_STEP_OK;
     }
@@ -405,6 +421,11 @@
             fprintf(fp, " succfr: ");
             MR_print_nondstackptr(fp, MR_succfr_slot(base_maxfr));
             fprintf(fp, " \n");
+#ifdef  MR_USE_MINIMAL_MODEL
+            fprintf(fp, " detfr:  ");
+            MR_print_detstackptr(fp, MR_table_detfr_slot(base_maxfr));
+            fprintf(fp, " \n");
+#endif
 
             level_number++;
             if (print_vars && base_maxfr > MR_nondet_stack_trace_bottom) {
@@ -434,6 +455,8 @@
     MR_Word                         *topfr;
     const MR_Label_Layout           *label_layout;
     const MR_Proc_Layout            *proc_layout;
+    MR_Code                         *redoip;
+    MR_Code                         *success;
     const char                      *problem;
 
     if (MR_find_matching_branch(fr, &branch)) {
@@ -503,13 +526,25 @@
                 MR_nondet_branch_infos[last].branch_topfr;
         MR_nondet_branch_info_next--;
     } else {
-        MR_Code *redoip;
-
-        redoip = MR_find_temp_redoip(fr);
-        if (redoip == NULL) {
+        redoip = MR_find_nofail_temp_redoip(fr);
+        if (redoip == NULL && MR_nofail_ip(MR_redoip_slot(fr))) {
             redoip = MR_redoip_slot(fr);
         }
 
+        if (redoip == NULL) {
+
+            fprintf(fp, " terminal top frame of a nondet side branch ");
+            MR_printnondstackptr(fr);
+            fprintf(fp, "\n");
+            MR_erase_temp_redoip(fr);
+
+            success = MR_succip_slot(fr);
+            base_sp = NULL;
+            base_curfr = MR_succfr_slot(fr);
+            topfr = fr;
+            result = MR_stack_walk_succip_layout(success, &label_layout,
+                        &problem);
+        } else {
         internal = MR_lookup_internal_by_addr(redoip);
         if (internal == NULL || internal->i_layout == NULL) {
             return "cannot find redoip label's layout structure";
@@ -540,6 +575,7 @@
         topfr = fr;
         result = MR_stack_walk_step(proc_layout, &label_layout,
                         &base_sp, &base_curfr, &problem);
+        }
 
         if (result != MR_STEP_OK) {
             return problem;
@@ -644,13 +680,36 @@
     MR_temp_frame_info_next++;
 }
 
+static MR_bool
+MR_nofail_ip(MR_Code *ip)
+{
+    if (ip == MR_ENTRY(MR_do_fail)) {
+        return MR_FALSE;
+    }
+    if (ip == MR_ENTRY(MR_do_trace_redo_fail_shallow)) {
+        return MR_FALSE;
+    }
+    if (ip == MR_ENTRY(MR_do_trace_redo_fail_deep)) {
+        return MR_FALSE;
+    }
+#ifdef  MR_USE_MINIMAL_MODEL
+    if (ip == MR_ENTRY(MR_RESUME_ENTRY)) {
+        return MR_FALSE;
+    }
+#endif
+
+    return MR_TRUE;
+}
+
 static MR_Code *
-MR_find_temp_redoip(MR_Word *fr)
+MR_find_nofail_temp_redoip(MR_Word *fr)
 {
     int     slot;
 
     for (slot = 0; slot < MR_temp_frame_info_next; slot++) {
-        if (fr == MR_temp_frame_infos[slot].temp_redofr) {
+        if (fr == MR_temp_frame_infos[slot].temp_redofr &&
+            MR_nofail_ip(MR_temp_frame_infos[slot].temp_redoip))
+        {
             return MR_temp_frame_infos[slot].temp_redoip;
         }
     }
@@ -903,6 +962,7 @@
             event_num = MR_event_num_framevar(base_curfr) + 1;
             call_num = MR_call_num_framevar(base_curfr);
             depth = MR_call_depth_framevar(base_curfr);
+
         }
 
         if (MR_standardize_event_details) {
@@ -922,6 +982,16 @@
         /* ensure that the remaining columns line up */
         fprintf(fp, "%21s", "");
     }
+
+#ifdef  MR_TABLE_DEBUG
+    if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+        MR_print_detstackptr(fp, base_sp);
+    } else {
+        MR_print_nondstackptr(fp, base_curfr);
+    }
+
+    fprintf(fp, " ");
+#endif
 }
 
 void
Index: runtime/mercury_stacks.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.c,v
retrieving revision 1.8
diff -u -b -r1.8 mercury_stacks.c
--- runtime/mercury_stacks.c	27 Dec 2001 07:25:23 -0000	1.8
+++ runtime/mercury_stacks.c	14 Mar 2003 03:35:46 -0000
@@ -33,6 +33,8 @@
 #include "mercury_runtime_util.h"
 #include <stdio.h>
 
+/***************************************************************************/
+
 #ifdef	MR_STACK_FRAME_STATS
 
 #include "mercury_dword.h"
@@ -110,22 +112,37 @@
 
 #endif	/* MR_STACK_FRAME_STATS */
 
+/***************************************************************************/
+
 #ifdef	MR_USE_MINIMAL_MODEL
 
-static	void	MR_print_gen_stack_entry(FILE *fp, MR_Integer i);
+static	int	MR_pneg_cut_depth = 0;
+
+static	void	MR_print_gen_stack_entry(FILE *fp, MR_Integer i,
+			MR_GenStackFrame *p);
+
 static	void	MR_cleanup_generator_ptr(MR_TrieNode generator_ptr);
+static	void	MR_print_cut_stack_entry(FILE *fp, MR_Integer i,
+			MR_CutStackFrame *p);
+
+static	void	MR_cleanup_consumer_ptr(MR_TrieNode consumer_ptr);
+static	void	MR_print_pneg_stack_entry(FILE *fp, MR_Integer i,
+			MR_PNegStackFrame *p);
+
+/***************************************************************************/
 
 void
 MR_push_generator(MR_Word *frame_addr, MR_TrieNode table_addr)
 {
-	MR_gen_stack[MR_gen_next].generator_frame = frame_addr;
-	MR_gen_stack[MR_gen_next].generator_table = table_addr;
+	MR_gen_stack[MR_gen_next].MR_generator_frame = frame_addr;
+	MR_gen_stack[MR_gen_next].MR_generator_table = table_addr;
 	MR_gen_next++;
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
 		printf("push ");
-		MR_print_gen_stack_entry(stdout, MR_gen_next - 1);
+		MR_print_gen_stack_entry(stdout, MR_gen_next - 1,
+			&MR_gen_stack[MR_gen_next - 1]);
 	}
 #endif
 }
@@ -136,11 +153,12 @@
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
 		printf("top ");
-		MR_print_gen_stack_entry(stdout, MR_gen_next - 1);
+		MR_print_gen_stack_entry(stdout, MR_gen_next - 1,
+			&MR_gen_stack[MR_gen_next - 1]);
 	}
 #endif
 
-	return MR_gen_stack[MR_gen_next - 1].generator_table->MR_subgoal;
+	return MR_gen_stack[MR_gen_next - 1].MR_generator_table->MR_subgoal;
 }
 
 void
@@ -151,7 +169,8 @@
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
 		printf("pop ");
-		MR_print_gen_stack_entry(stdout, MR_gen_next);
+		MR_print_gen_stack_entry(stdout, MR_gen_next,
+			&MR_gen_stack[MR_gen_next]);
 	}
 #endif
 }
@@ -159,38 +178,46 @@
 void
 MR_print_gen_stack(FILE *fp)
 {
-#ifdef	MR_TABLE_DEBUG
-	int	i;
+	MR_print_any_gen_stack(fp, MR_gen_next, MR_gen_stack);
+}
 
-	if (MR_tabledebug) {
-		for (i = MR_gen_next - 1; i >= 0; i--) {
-			MR_print_gen_stack_entry(fp, i);
-		}
+void
+MR_print_any_gen_stack(FILE *fp, MR_Integer gen_next,
+	MR_GenStackFrame *gen_block)
+{
+	MR_Integer	i;
+
+	fprintf(fp, "gen stack size: %d:\n", (int) gen_next);
+	for (i = gen_next - 1; i >= 0; i--) {
+		MR_print_gen_stack_entry(fp, i, &MR_gen_stack[i]);
 	}
-#endif
 }
 
 static void
-MR_print_gen_stack_entry(FILE *fp, MR_Integer i)
+MR_print_gen_stack_entry(FILE *fp, MR_Integer i, MR_GenStackFrame *p)
 {
-#ifdef	MR_TABLE_DEBUG
-	if (MR_tabledebug) {
+	MR_SubgoalDebug	*subgoal_debug;
+
 		fprintf(fp, "gen %ld = <", (long) i);
-		MR_print_nondstackptr(fp, MR_gen_stack[i].generator_frame);
-		fprintf(fp, ", %p>\n", MR_gen_stack[i].generator_table);
-	}
-#endif
+	MR_print_nondstackptr(fp, p->MR_generator_frame);
+	subgoal_debug = MR_lookup_subgoal_debug_addr(
+		p->MR_generator_table->MR_subgoal);
+	fprintf(fp, ", %s>\n", MR_subgoal_debug_name(subgoal_debug));
 }
 
+/***************************************************************************/
+
 void
 MR_commit_mark(void)
 {
 	MR_restore_transient_registers();
 
-	MR_cut_stack[MR_cut_next].frame = MR_maxfr;
-	MR_cut_stack[MR_cut_next].gen_next = MR_gen_next;
-	MR_cut_stack[MR_cut_next].generators = NULL;
+	MR_cut_stack[MR_cut_next].MR_cut_frame = MR_maxfr;
+	MR_cut_stack[MR_cut_next].MR_cut_gen_next = MR_gen_next;
+	MR_cut_stack[MR_cut_next].MR_cut_generators = NULL;
+	MR_cut_stack[MR_cut_next].MR_cut_depth = MR_pneg_cut_depth;
 	MR_cut_next++;
+	MR_pneg_cut_depth++;
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
@@ -207,17 +234,19 @@
 	MR_CutGeneratorList	g;
 
 	--MR_cut_next;
+	--MR_pneg_cut_depth;
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
 		printf("commit stack next down to %ld\n",
 			(long) MR_cut_next);
 		printf("setting generator stack next back to %ld from %ld\n",
-			(long) MR_cut_stack[MR_cut_next].gen_next,
+			(long) MR_cut_stack[MR_cut_next].MR_cut_gen_next,
 			(long) MR_gen_next);
 
-		if (MR_gen_next != MR_cut_stack[MR_cut_next].gen_next) {
-			if (MR_gen_next <= MR_cut_stack[MR_cut_next].gen_next)
+		if (MR_gen_next != MR_cut_stack[MR_cut_next].MR_cut_gen_next) {
+			if (MR_gen_next <=
+				MR_cut_stack[MR_cut_next].MR_cut_gen_next)
 			{
 				printf("MR_gen_next %ld, MR_cut_next %ld, "
 					"MR_cut_stack[MR_cut_next].gen_next "
@@ -225,21 +254,21 @@
 					(long) MR_gen_next,
 					(long) MR_cut_next,
 					(long) MR_cut_stack[MR_cut_next].
-						gen_next);
+						MR_cut_gen_next);
 				MR_fatal_error("GEN_NEXT ASSERTION FAILURE");
 			}
 		}
 	}
 #endif
 
-	for (g = MR_cut_stack[MR_cut_next].generators; g != NULL;
-		g = g->next_generator)
+	for (g = MR_cut_stack[MR_cut_next].MR_cut_generators; g != NULL;
+		g = g->MR_cut_next_generator)
 	{
-		MR_cleanup_generator_ptr(g->generator_ptr);
+		MR_cleanup_generator_ptr(g->MR_cut_generator_ptr);
 	}
 
-	MR_cut_stack[MR_cut_next].generators = NULL;
-	MR_gen_next = MR_cut_stack[MR_cut_next].gen_next;
+	MR_cut_stack[MR_cut_next].MR_cut_generators = NULL;
+	MR_gen_next = MR_cut_stack[MR_cut_next].MR_cut_gen_next;
 }
 
 void
@@ -247,16 +276,22 @@
 {
 	struct MR_CutGeneratorListNode	*node;
 
+	if (MR_cut_next <= 0) {
+		return;
+	}
+
 	node = MR_GC_NEW(struct MR_CutGeneratorListNode);
-	node->generator_ptr = generator_ptr;
-	node->next_generator = MR_cut_stack[MR_cut_next - 1].generators;
-	MR_cut_stack[MR_cut_next - 1].generators = node;
+	node->MR_cut_generator_ptr = generator_ptr;
+	node->MR_cut_next_generator =
+		MR_cut_stack[MR_cut_next - 1].MR_cut_generators;
+	MR_cut_stack[MR_cut_next - 1].MR_cut_generators = node;
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
-		printf("registering generator %p -> %p "
+		printf("registering generator %p -> %s "
 			"at commit stack level %d\n",
-			generator_ptr, generator_ptr->MR_subgoal,
+			generator_ptr,
+			MR_subgoal_addr_name(generator_ptr->MR_subgoal),
 			MR_cut_next - 1);
 	}
 #endif
@@ -265,25 +300,219 @@
 static void
 MR_cleanup_generator_ptr(MR_TrieNode generator_ptr)
 {
-	if (generator_ptr->MR_subgoal->status == MR_SUBGOAL_COMPLETE) {
+	if (generator_ptr->MR_subgoal->MR_sg_status == MR_SUBGOAL_COMPLETE) {
 		/* there is nothing to do, everything is OK */
 #ifdef	MR_TABLE_DEBUG
 		if (MR_tabledebug) {
-			printf("no cleanup: generator %p -> %p is complete\n",
-				generator_ptr, generator_ptr->MR_subgoal);
+			printf("no cleanup: generator %p -> %s is complete\n",
+				generator_ptr, MR_subgoal_addr_name(
+					generator_ptr->MR_subgoal));
 		}
 #endif
 	} else {
 		/* this generator will never complete the subgoal */
 #ifdef	MR_TABLE_DEBUG
 		if (MR_tabledebug) {
-			printf("cleanup: generator %p -> %p deleted\n",
-				generator_ptr, generator_ptr->MR_subgoal);
+			printf("cleanup: generator %p -> %s deleted\n",
+				generator_ptr, MR_subgoal_addr_name(
+					generator_ptr->MR_subgoal));
 		}
 #endif
 
 		generator_ptr->MR_subgoal = NULL;
 	}
 }
+
+void
+MR_print_cut_stack(FILE *fp)
+{
+	MR_print_any_cut_stack(fp, MR_cut_next, MR_cut_stack);
+}
+
+void
+MR_print_any_cut_stack(FILE *fp, MR_Integer cut_next,
+	MR_CutStackFrame *cut_block)
+{
+	MR_Integer	i;
+
+	fprintf(fp, "cut stack size: %d:\n", (int) cut_next);
+	for (i = cut_next - 1; i >= 0; i--) {
+		MR_print_cut_stack_entry(fp, i, &cut_block[i]);
+	}
+}
+
+static void
+MR_print_cut_stack_entry(FILE *fp, MR_Integer i, MR_CutStackFrame *p)
+{
+	MR_SubgoalDebug		*subgoal_debug;
+	MR_CutGeneratorList	gen_list;
+
+	fprintf(fp, "cut %ld = <", (long) i);
+	MR_print_nondstackptr(fp, p->MR_cut_frame);
+	fprintf(fp, ", %d>:", p->MR_cut_gen_next);
+
+	gen_list = p->MR_cut_generators;
+	while (gen_list != NULL) {
+		if (gen_list->MR_cut_generator_ptr == NULL) {
+			fprintf(fp, " <NULL>");
+		} else {
+			subgoal_debug = MR_lookup_subgoal_debug_addr(
+				gen_list->MR_cut_generator_ptr->MR_subgoal);
+			fprintf(fp, " <%s>",
+				MR_subgoal_debug_name(subgoal_debug));
+		}
+
+		gen_list = gen_list->MR_cut_next_generator;
+	}
+
+	fprintf(fp, "\n");
+}
+
+/***************************************************************************/
+
+void
+MR_register_suspension(MR_Subgoal *subgoal)
+{
+	MR_PNegConsumerList	node_ptr;
+
+	if (MR_pneg_next <= 0) {
+		return;
+	}
+
+	node_ptr = MR_TABLE_NEW(MR_PNegConsumerListNode);
+	node_ptr->MR_pneg_consumer_ptr = subgoal;
+	node_ptr->MR_pneg_next_consumer = 
+		MR_pneg_stack[MR_pneg_next - 1].MR_pneg_consumers;
+	MR_pneg_stack[MR_pneg_next - 1].MR_pneg_consumers = node_ptr;
+}
+
+void
+MR_pneg_enter_cond(void)
+{
+	MR_restore_transient_registers();
+
+	MR_pneg_stack[MR_pneg_next].MR_pneg_frame = MR_maxfr;
+	MR_pneg_stack[MR_pneg_next].MR_pneg_gen_next = MR_gen_next;
+	MR_pneg_stack[MR_pneg_next].MR_pneg_depth = MR_pneg_cut_depth;
+	MR_pneg_stack[MR_pneg_next].MR_pneg_consumers = NULL;
+	MR_pneg_next++;
+	MR_pneg_cut_depth++;
+
+#ifdef	MR_TABLE_DEBUG
+	if (MR_tabledebug) {
+		printf("pneg stack next up to %ld\n", (long) MR_pneg_next);
+	}
+#endif
+
+	MR_save_transient_registers();
+}
+
+void
+MR_pneg_enter_then(void)
+{
+	MR_PNegConsumerList	l;
+	MR_PNegConsumerList	next;
+
+	MR_restore_transient_registers();
+
+	--MR_pneg_next;
+	--MR_pneg_cut_depth;
+
+#ifdef	MR_TABLE_DEBUG
+	if (MR_tabledebug) {
+		printf("pneg stack down up to %ld (then)\n",
+			(long) MR_pneg_next);
+	}
+#endif
+
+	for (l = MR_pneg_stack[MR_pneg_next].MR_pneg_consumers; l != NULL;
+		l = next)
+	{
+		next = l->MR_pneg_next_consumer;
+		MR_table_free(l);
+	}
+
+	MR_save_transient_registers();
+}
+
+void
+MR_pneg_enter_else(void)
+{
+	MR_PNegConsumerList	l;
+	MR_PNegConsumerList	next;
+
+	MR_restore_transient_registers();
+
+	--MR_pneg_next;
+	--MR_pneg_cut_depth;
+
+#ifdef	MR_TABLE_DEBUG
+	if (MR_tabledebug) {
+		printf("pneg stack down up to %ld (else)\n",
+			(long) MR_pneg_next);
+	}
+#endif
+
+	for (l = MR_pneg_stack[MR_pneg_next].MR_pneg_consumers; l != NULL;
+		l = next)
+	{
+		next = l->MR_pneg_next_consumer;
+		if (l->MR_pneg_consumer_ptr->MR_sg_status !=
+			MR_SUBGOAL_COMPLETE)
+		{
+			MR_fatal_error("MR_pneg_enter_else: failing out of "
+				"negated context with incomplete consumer");
+		}
+
+		MR_table_free(l);
+	}
+
+	MR_save_transient_registers();
+}
+
+void
+MR_print_pneg_stack(FILE *fp)
+{
+	MR_print_pneg_stack_entry(fp, MR_pneg_next, MR_pneg_stack);
+}
+
+void
+MR_print_any_pneg_stack(FILE *fp, MR_Integer pneg_next,
+	MR_PNegStackFrame *pneg_block)
+{
+	MR_Integer	i;
+
+	fprintf(fp, "pneg stack size: %d:\n", (int) pneg_next);
+	for (i = MR_pneg_next - 1; i >= 0; i--) {
+		MR_print_pneg_stack_entry(fp, i, &pneg_block[i]);
+	}
+}
+
+static void
+MR_print_pneg_stack_entry(FILE *fp, MR_Integer i, MR_PNegStackFrame *p)
+{
+	MR_PNegConsumerList	l;
+
+	fprintf(fp, "pneg stack entry %d:\n", (int) i);
+	fprintf(fp, "gen next: %d\n", (int) p->MR_pneg_gen_next);
+	fprintf(fp, "frame: ");
+	MR_print_nondstackptr(fp, p->MR_pneg_frame);
+	fprintf(fp, "\npneg+cut stack depth %d:\n", (int) p->MR_pneg_depth);
+
+	if (p->MR_pneg_consumers == NULL) {
+		fprintf(fp, "no consumers\n");
+	} else {
+		int	n;
+
+		for (n = 1, l = p->MR_pneg_consumers; l != NULL;
+			l = l->MR_pneg_next_consumer, n++)
+		{
+			fprintf(fp, "consumer %d: %s\n", n,
+				MR_subgoal_addr_name(l->MR_pneg_consumer_ptr));
+		}
+	}
+}
+
+/***************************************************************************/
 
 #endif	/* MR_USE_MINIMAL_MODEL */
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.37
diff -u -b -r1.37 mercury_stacks.h
--- runtime/mercury_stacks.h	22 Nov 2002 03:17:53 -0000	1.37
+++ runtime/mercury_stacks.h	10 Mar 2003 08:28:43 -0000
@@ -460,35 +460,67 @@
 
 /* DEFINITIONS FOR GENERATOR STACK FRAMES */
 
-typedef struct MR_GeneratorStackFrameStruct {
-	MR_Word			*generator_frame;
-	MR_TrieNode		generator_table;
-} MR_GeneratorStackFrame;
+struct MR_GenStackFrameStruct {
+	MR_Word			*MR_generator_frame;
+	MR_TrieNode		MR_generator_table;
+};
 
 extern	void			MR_push_generator(MR_Word *frame_addr,
 					MR_TrieNode table_addr);
 extern	MR_Subgoal		*MR_top_generator_table(void);
 extern	void			MR_pop_generator(void);
 extern	void			MR_print_gen_stack(FILE *fp);
+extern	void			MR_print_any_gen_stack(FILE *fp,
+					MR_Integer gen_next,
+					MR_GenStackFrame *gen_block);
 
 /* DEFINITIONS FOR CUT STACK FRAMES */
 
 typedef struct MR_CutGeneratorListNode *MR_CutGeneratorList;
 struct MR_CutGeneratorListNode {
-	MR_TrieNode		generator_ptr;
-	MR_CutGeneratorList	next_generator;
+	MR_TrieNode		MR_cut_generator_ptr;
+	MR_CutGeneratorList	MR_cut_next_generator;
 };
 
-typedef struct MR_CutStackFrameStruct {
-	MR_Word			*frame;
-	MR_Integer		gen_next;
-	MR_CutGeneratorList	generators;
-} MR_CutStackFrame;
+struct MR_CutStackFrameStruct {
+	MR_Word			*MR_cut_frame;
+	MR_Integer		MR_cut_gen_next;
+	MR_CutGeneratorList	MR_cut_generators;
+	int			MR_cut_depth;
+};
 
 extern	void			MR_commit_mark(void);
 extern	void			MR_commit_cut(void);
 
 extern	void			MR_register_generator_ptr(MR_TrieNode);
+extern	void			MR_print_cut_stack(FILE *fp);
+extern	void			MR_print_any_cut_stack(FILE *fp,
+					MR_Integer cut_next,
+					MR_CutStackFrame *cut_block);
+
+/* DEFINITIONS FOR PNEG STACK FRAMES */
+
+struct MR_PNegConsumerListNodeStruct {
+	MR_Subgoal		*MR_pneg_consumer_ptr;
+	MR_PNegConsumerList	MR_pneg_next_consumer;
+};
+
+struct MR_PNegStackFrameStruct {
+	MR_Word			*MR_pneg_frame;
+	MR_Integer		MR_pneg_gen_next;
+	MR_PNegConsumerList	MR_pneg_consumers;
+	int			MR_pneg_depth;
+};
+
+extern	void			MR_register_suspension(MR_Subgoal *subgoal);
+extern	void			MR_pneg_enter_cond(void);
+extern	void			MR_pneg_enter_then(void);
+extern	void			MR_pneg_enter_else(void);
+
+extern	void			MR_print_pneg_stack(FILE *fp);
+extern	void			MR_print_any_pneg_stack(FILE *fp,
+					MR_Integer pneg_next,
+					MR_PNegStackFrame *pneg_block);
 
 #endif	/* MR_USE_MINIMAL_MODEL */
 
Index: runtime/mercury_tabling.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_tabling.c,v
retrieving revision 1.55
diff -u -b -r1.55 mercury_tabling.c
--- runtime/mercury_tabling.c	10 Feb 2003 17:12:02 -0000	1.55
+++ runtime/mercury_tabling.c	10 Mar 2003 08:22:08 -0000
@@ -7,11 +7,16 @@
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
 
+/*
+** This module contains the functions related to tabling that are not
+** specific to minimal model tabling.
+*/
+
 #include "mercury_imp.h"
 
 #include "mercury_type_info.h"
-#include "mercury_ho_call.h"
 #include "mercury_array_macros.h"
+#include "mercury_builtin_types.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1256,1081 +1261,53 @@
 
 /*---------------------------------------------------------------------------*/
 
-#ifdef  MR_USE_MINIMAL_MODEL
-
-/*
-** Save the current state of the Mercury abstract machine, so that the
-** current computation may be suspended for a while, and restored later.
-** The generator_{maxfr,sp} arguments give the points from which we need
-** to copy the nondet and the det stacks. The parts of those stacks below
-** the given points will not change between the suspension and the resumption
-** of this state, or if they do, the stack segments in the saved state
-** will be extended (via extend_consumer_stacks).
-*/
-
-static void
-save_state(MR_SavedState *saved_state,
-        MR_Word *generator_maxfr, MR_Word *generator_sp,
-        const char *who, const char *what)
-{
-        MR_restore_transient_registers();
-
-  #ifdef MR_HIGHLEVEL_CODE
-        MR_fatal_error("sorry, not implemented: "
-                "minimal model tabling with --high-level-code");
-  #else
-        saved_state->succ_ip = MR_succip;
-        saved_state->s_p = MR_sp;
-        saved_state->cur_fr = MR_curfr;
-        saved_state->max_fr = MR_maxfr;
-
-        saved_state->non_stack_block_start = generator_maxfr + 1;
-        if (MR_maxfr > generator_maxfr) {
-                saved_state->non_stack_block_size = MR_maxfr - generator_maxfr;
-                saved_state->non_stack_block =
-                        MR_table_allocate_words(saved_state->non_stack_block_size);
-                MR_table_copy_words(saved_state->non_stack_block,
-                        saved_state->non_stack_block_start,
-                        saved_state->non_stack_block_size);
-        } else {
-                saved_state->non_stack_block_size = 0;
-                saved_state->non_stack_block = NULL;
-        }
-
-        saved_state->det_stack_block_start = generator_sp;
-        if (MR_sp > generator_sp) {
-                saved_state->det_stack_block_size = (MR_sp - 1) - generator_sp;
-                saved_state->det_stack_block =
-                        MR_table_allocate_words(saved_state->det_stack_block_size);
-                MR_table_copy_words(saved_state->det_stack_block,
-                        saved_state->det_stack_block_start,
-                        saved_state->det_stack_block_size);
-        } else {
-                saved_state->det_stack_block_size = 0;
-                saved_state->det_stack_block = NULL;
-        }
-
-  #endif /* ! MR_HIGHLEVEL_CODE */
-
-        saved_state->gen_next = MR_gen_next;
-        saved_state->generator_stack_block = MR_table_allocate_bytes(
-                        MR_gen_next * sizeof(MR_GeneratorStackFrame));
-        MR_table_copy_bytes(saved_state->generator_stack_block,
-                MR_gen_stack, MR_gen_next * sizeof(MR_GeneratorStackFrame));
-
-        saved_state->cut_next = MR_cut_next;
-        saved_state->cut_stack_block = MR_table_allocate_bytes(
-                        MR_cut_next * sizeof(MR_CutStackFrame));
-        MR_table_copy_bytes(saved_state->cut_stack_block,
-                MR_cut_stack, MR_cut_next * sizeof(MR_CutStackFrame));
-
-  #ifdef MR_USE_TRAIL
-        /*
-        ** Saving the trail state here would not be sufficient to handle
-        ** the combination of trailing and minimal model tabling.
-        ** Consider the following sequence of events:
-        **
-        **      execution enters a goal being committed across
-        **      a new entry is pushed on the trail
-        **      a tabled goal suspends,
-        **              causing the saving of a trail segment
-        **              and then a failure
-        **      the goal being committed across fails,
-        **              which invokes a failed commit on the trail entry
-        **      ...
-        **      the tabled goal is resumed,
-        **              causing the restoring of the saved trail segment
-        **              and then a success
-        **      the goal being committed across now succeeds,
-        **              which invokes a successful commit on the trail entry
-        **
-        ** The trail handler will be thoroughly confused by such a sequence.
-        */
-
-        MR_fatal_error("Sorry, not implemented: "
-                "can't have both minimal model tabling and trailing");
-  #endif
-
-  #ifdef MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("\n%s saves %s stacks: ", who, what);
-                printf("%d non, %d det, %d generator, %d cut\n",
-                        saved_state->non_stack_block_size,
-                        saved_state->det_stack_block_size,
-                        MR_gen_next, MR_cut_next);
-
-    #ifdef MR_HIGHLEVEL_CODE
-                MR_fatal_error("sorry, not implemented: "
-                        "minimal model tabling with --high-level-code");
-    #else
-                printf("non region from ");
-                MR_printnondstackptr(saved_state->non_stack_block_start);
-                printf(" to ");
-                MR_printnondstackptr(MR_maxfr);
-                printf(" (both inclusive)\n");
-                printf("stored at %p to %p (both inclusive)\n",
-                        saved_state->non_stack_block,
-                        saved_state->non_stack_block +
-                                saved_state->non_stack_block_size - 1);
-
-                printf("det region from ");
-                MR_printdetstackptr(saved_state->det_stack_block_start);
-                printf(" to ");
-                MR_printdetstackptr(MR_sp);
-                printf(" (both inclusive)\n");
-                printf("stored at %p to %p (both inclusive)\n",
-                        saved_state->det_stack_block,
-                        saved_state->det_stack_block +
-                                saved_state->det_stack_block_size - 1);
-
-                printf("succip = %p, sp = ", (void *) MR_succip);
-                MR_printdetstackptr(MR_sp);
-                printf("\nmaxfr = ");
-                MR_printnondstackptr(MR_maxfr);
-                printf(", curfr = ");
-                MR_printnondstackptr(MR_curfr);
-                printf("\n\n");
-    #endif
-
-                MR_print_gen_stack(stdout);
-
-    #ifndef MR_HIGHLEVEL_CODE
-                if (MR_tablestackdebug) {
-                        MR_dump_nondet_stack(stdout, MR_maxfr);
-                }
-    #endif
-        }
-  #endif /* MR_TABLE_DEBUG */
-
-        MR_save_transient_registers();
-}
-
-/*
-** Restore the state of the Mercury abstract machine from saved_state.
-*/
-
-static void
-restore_state(MR_SavedState *saved_state, const char *who, const char *what)
-{
-        MR_restore_transient_registers();
-
-  #ifdef MR_HIGHLEVEL_CODE
-
-        MR_fatal_error("sorry, not implemented: "
-                "minimal model tabling with --high-level-code");
-
-  #else
-
-        MR_succip = saved_state->succ_ip;
-        MR_sp = saved_state->s_p;
-        MR_curfr = saved_state->cur_fr;
-        MR_maxfr = saved_state->max_fr;
-
-        MR_table_copy_words(saved_state->non_stack_block_start,
-                saved_state->non_stack_block,
-                saved_state->non_stack_block_size);
-
-        MR_table_copy_words(saved_state->det_stack_block_start,
-                saved_state->det_stack_block,
-                saved_state->det_stack_block_size);
-
-  #endif
-
-        MR_gen_next = saved_state->gen_next;
-        MR_table_copy_bytes(MR_gen_stack, saved_state->generator_stack_block,
-                saved_state->gen_next * sizeof(MR_GeneratorStackFrame));
-
-        MR_cut_next = saved_state->cut_next;
-        MR_table_copy_bytes(MR_cut_stack, saved_state->cut_stack_block,
-                saved_state->cut_next * sizeof(MR_CutStackFrame));
-
-  #ifdef MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("\n%s restores %s stacks: ", who, what);
-                printf("%d non, %d det, %d generator, %d cut\n",
-                        saved_state->non_stack_block_size,
-                        saved_state->det_stack_block_size,
-                        saved_state->gen_next, saved_state->cut_next);
-
-                printf("non region from ");
-                MR_printnondstackptr(saved_state->non_stack_block_start);
-                printf(" to ");
-                MR_printnondstackptr(saved_state->non_stack_block_start +
-                        saved_state->non_stack_block_size - 1);
-                printf(" (both inclusive)\n");
-                printf("stored at %p to %p (both inclusive)\n",
-                        saved_state->non_stack_block,
-                        saved_state->non_stack_block +
-                                saved_state->non_stack_block_size - 1);
-
-                printf("det region from ");
-                MR_printdetstackptr(saved_state->det_stack_block_start);
-                printf(" to ");
-                MR_printdetstackptr(saved_state->det_stack_block_start +
-                        saved_state->det_stack_block_size - 1);
-                printf(" (both inclusive)\n");
-                printf("stored at %p to %p (both inclusive)\n",
-                        saved_state->det_stack_block,
-                        saved_state->det_stack_block +
-                                saved_state->det_stack_block_size - 1);
-
-                printf("succip = %p, sp = ", (void *) MR_succip);
-                MR_printdetstackptr(MR_sp);
-                printf("\nmaxfr = ");
-                MR_printnondstackptr(MR_maxfr);
-                printf(", curfr = ");
-                MR_printnondstackptr(MR_curfr);
-                printf("\n");
-
-                MR_print_gen_stack(stdout);
-
-                if (MR_tablestackdebug) {
-                        MR_dump_nondet_stack_from_layout(stdout, MR_maxfr);
-                }
-        }
-  #endif /* MR_table_debug */
-
-        MR_save_transient_registers();
-}
-
-static void
-print_saved_state_stacks(MR_SavedState *saved_state)
+void
+MR_print_answerblock(FILE *fp, const MR_Proc_Layout *proc,
+	MR_Word *answer_block)
 {
+	const MR_PseudoTypeInfo	*ptis;
+	MR_PseudoTypeInfo	pti;
+	MR_TypeCtorInfo		tci;
+	int			num_inputs;
+	int			num_outputs;
         int     i;
 
-        printf("saved state parameters:\n");
-        printf("succip:\t");
-        MR_printlabel(stdout, saved_state->succ_ip);
-        printf("sp:\t");
-        MR_printdetstackptr(saved_state->s_p);
-        printf("\ncurfr:\t");
-        MR_printnondstackptr(saved_state->cur_fr);
-        printf("\nmaxfr:\t");
-        MR_printnondstackptr(saved_state->max_fr);
-
-        printf("\n\nnondet stack block: %d words from %p\n",
-                saved_state->non_stack_block_size,
-                saved_state->non_stack_block_start);
-        for (i = 0; i < saved_state->non_stack_block_size; i++) {
-                printf("%2d: %x\n", i, saved_state->non_stack_block[i]);
-        }
-
-        printf("\ndet stack block: %d words from %p\n",
-                saved_state->det_stack_block_size,
-                saved_state->det_stack_block_start);
-        for (i = 0; i < saved_state->det_stack_block_size; i++) {
-                printf("%2d: %x\n", i, saved_state->det_stack_block[i]);
-        }
-
-        printf("\n");
-}
-
-/*
-** The saved state of a consumer for a subgoal (say subgoal A) includes
-** the stack segments between the tops of the stack at the time that
-** A's generator was entered and the time that A's consumer was entered.
-** When A becomes a follower of another subgoal B, the responsibility for
-** scheduling A's consumers passes to B's generator. Since by definition
-** B's nondet stack frame is lower in the stack than A's generator's,
-** we need to extend the stack segments of A's consumers to also include
-** the parts of the stacks between the generator of B and the generator of A.
-*/
-
-MR_declare_entry(mercury__table_builtin__table_nondet_resume_1_0);
-
-static void
-extend_consumer_stacks(MR_Subgoal *leader, MR_Consumer *suspension)
-{
-        MR_Word *arena_block;
-        MR_Word *arena_start;
-        MR_Word arena_size;
-        MR_Word extension_size;
-        MR_Word *saved_fr;
-        MR_Word *real_fr;
-        MR_Word frame_size;
-        MR_Word offset;
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tablestackdebug) {
-                printf("\nextending saved consumer stacks\n");
-                print_saved_state_stacks(&suspension->saved_state);
-        }
-#endif
-
-        arena_start = leader->generator_sp;
-        extension_size = suspension->saved_state.det_stack_block_start
-                        - arena_start;
-        arena_size  = extension_size
-                        + suspension->saved_state.det_stack_block_size;
-        if (arena_size != 0) {
-                assert(arena_start + arena_size
-                                == suspension->saved_state.s_p - 1);
-        }
-
-        arena_block = MR_table_allocate_words(arena_size);
-
-        MR_table_copy_words(arena_block, arena_start, extension_size);
-        MR_table_copy_words(arena_block + extension_size,
-                suspension->saved_state.det_stack_block,
-                suspension->saved_state.det_stack_block_size);
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("extending det stack of suspension %p for %p\n",
-                        suspension, leader);
-                printf("start: old %p, new %p\n",
-                        suspension->saved_state.det_stack_block_start,
-                        arena_start);
-                printf("size:  old %d, new %d\n",
-                        suspension->saved_state.det_stack_block_size,
-                        arena_size);
-                printf("block: old %p, new %p\n",
-                        suspension->saved_state.det_stack_block,
-                        arena_block);
-        }
-#endif
-
-        suspension->saved_state.det_stack_block = arena_block;
-        suspension->saved_state.det_stack_block_size = arena_size;
-        suspension->saved_state.det_stack_block_start = arena_start;
-
-        arena_start = leader->generator_maxfr + 1;
-        extension_size = suspension->saved_state.non_stack_block_start
-                        - arena_start;
-        arena_size  = extension_size
-                        + suspension->saved_state.non_stack_block_size;
-        assert(leader->generator_maxfr + arena_size
-                        == suspension->saved_state.max_fr);
-
-        arena_block = MR_table_allocate_words(arena_size);
-
-        MR_table_copy_words(arena_block, arena_start, extension_size);
-        MR_table_copy_words(arena_block + extension_size,
-                suspension->saved_state.non_stack_block,
-                suspension->saved_state.non_stack_block_size);
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("extending non stack of suspension %p for %p\n",
-                        suspension, leader);
-                printf("start: old %p, new %p\n",
-                        suspension->saved_state.non_stack_block_start,
-                        arena_start);
-                printf("size:  old %d, new %d\n",
-                        suspension->saved_state.non_stack_block_size,
-                        arena_size);
-                printf("block: old %p, new %p\n",
-                        suspension->saved_state.non_stack_block,
-                        arena_block);
-        }
-#endif
-
-        suspension->saved_state.non_stack_block = arena_block;
-        suspension->saved_state.non_stack_block_size = arena_size;
-        suspension->saved_state.non_stack_block_start = arena_start;
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tablestackdebug) {
-                printf("\nbefore pickling nondet stack\n");
-                print_saved_state_stacks(&suspension->saved_state);
-        }
-#endif
-
-        saved_fr = suspension->saved_state.non_stack_block +
-                suspension->saved_state.non_stack_block_size - 1;
-        real_fr = suspension->saved_state.non_stack_block_start +
-                suspension->saved_state.non_stack_block_size - 1;
-        while (saved_fr > suspension->saved_state.non_stack_block) {
-                frame_size = real_fr - MR_prevfr_slot(saved_fr);
-
-                if (saved_fr - frame_size
-                        > suspension->saved_state.non_stack_block)
-                {
-                        *MR_redoip_addr(saved_fr) =
-                                (MR_Word) MR_ENTRY(MR_do_fail);
-
-#ifdef  MR_TABLE_DEBUG
-                        if (MR_tabledebug) {
-                                printf("do_fail to redoip at %p (%d)\n",
-                                        MR_redoip_addr(saved_fr),
-                                        MR_redoip_addr(saved_fr) -
-                                        suspension->
-                                        saved_state.non_stack_block);
-                        }
-#endif
-                } else {
-                        *MR_redoip_addr(saved_fr) = (MR_Word)
-                                MR_ENTRY(mercury__table_builtin__table_nondet_resume_1_0);
-#ifdef  MR_TABLE_DEBUG
-                        if (MR_tabledebug) {
-                                printf("resume to redoip at %p (%d)\n",
-                                        MR_redoip_addr(saved_fr),
-                                        MR_redoip_addr(saved_fr) -
-                                        suspension->
-                                        saved_state.non_stack_block);
-                        }
-#endif
-                }
-
-                saved_fr -= frame_size;
-                real_fr -= frame_size;
-        }
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tablestackdebug) {
-                printf("\nfinished extending saved consumer stacks\n");
-                print_saved_state_stacks(&suspension->saved_state);
-        }
-#endif
-}
-
-/*
-** When we discover that two subgoals depend on each other, neither can be
-** completed alone. We therefore pass responsibility for completing all
-** the subgoals in an SCC to the subgoal whose nondet stack frame is
-** lowest in the nondet stack.
-*/
-
-static void
-make_subgoal_follow_leader(MR_Subgoal *this_follower, MR_Subgoal *leader)
-{
-        MR_Consumer             *suspension;
-        MR_SubgoalList          sub_followers;
-        MR_ConsumerList         suspend_list;
-
-        MR_restore_transient_registers();
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("making %p follow %p\n", this_follower, leader);
-        }
-#endif
-
-        for (sub_followers = this_follower->followers;
-                sub_followers != NULL; sub_followers = sub_followers->next)
-        {
-                for (suspend_list = sub_followers->item->consumer_list;
-                        suspend_list != NULL;
-                        suspend_list = suspend_list->next)
-                {
-                        MR_save_transient_registers();
-                        extend_consumer_stacks(leader, suspend_list->item);
-                        MR_restore_transient_registers();
-                }
-        }
-
-        this_follower->leader = leader;
-        *(leader->followers_tail) = this_follower->followers;
-        this_follower->followers = NULL;
-
-        MR_save_transient_registers();
-}
-
-/*
-** The following procedure saves the state of the Mercury runtime
-** so that it may be used in the table_nondet_resume procedure below to return
-** answers through this saved state. The procedure table_nondet_suspend is
-** declared as nondet but the code below is obviously of detism failure;
-** the reason for this is quite simple. Normally when a nondet proc
-** is called it will first return all of its answers and then fail. In the
-** case of calls to this procedure this is reversed: first the call will fail
-** then later on, when the answers are found, answers will be returned.
-** It is also important to note that the answers are returned not from the
-** procedure that was originally called (table_nondet_suspend) but from the
-** procedure table_nondet_resume. So essentially what is below is the code
-** to do the initial fail; the code to return the answers is in
-** table_nondet_resume.
-*/
-
-#ifndef MR_HIGHLEVEL_CODE
-
-MR_declare_entry(mercury__table_builtin__table_nondet_resume_1_0);
-MR_declare_entry(MR_do_trace_redo_fail);
-MR_declare_entry(MR_table_nondet_commit);
-MR_define_extern_entry(mercury__table_builtin__table_nondet_suspend_2_0);
-MR_MAKE_PROC_LAYOUT(mercury__table_builtin__table_nondet_suspend_2_0,
-        MR_DETISM_NON, 0, MR_LONG_LVAL_TYPE_UNKNOWN,
-        MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
-MR_BEGIN_MODULE(table_nondet_suspend_module)
-        MR_init_entry_sl(mercury__table_builtin__table_nondet_suspend_2_0);
-        MR_INIT_PROC_LAYOUT_ADDR(mercury__table_builtin__table_nondet_suspend_2_0);
-MR_BEGIN_CODE
-
-MR_define_entry(mercury__table_builtin__table_nondet_suspend_2_0);
-{
-        MR_TrieNode     table;
-        MR_Subgoal      *subgoal;
-        MR_Consumer     *consumer;
-        MR_ConsumerList listnode;
-        MR_Integer      cur_gen;
-        MR_Integer      cur_cut;
-        MR_Word         *fr;
-        MR_Word         *prev_fr;
-        MR_Word         *stop_addr;
-        MR_Word         offset;
-        MR_Word         *clobber_addr;
-
-        /*
-        ** This frame is not used in table_nondet_suspend, but it is copied
-        ** to the suspend list as part of the saved nondet stack fragment,
-        ** and it *will* be used when table_nondet_resume copies back the
-        ** nondet stack fragment. The framevar slot is for use by
-        ** table_nondet_resume.
-        */
-        MR_mkframe("mercury__table_builtin__table_nondet_suspend", 1,
-                MR_ENTRY(MR_do_fail));
-
-        table = (MR_TrieNode) MR_r1;
-        subgoal = table->MR_subgoal;
-        consumer = MR_table_allocate_bytes(sizeof(MR_Consumer));
-        consumer->remaining_answer_list_ptr = &subgoal->answer_list;
-
-        MR_save_transient_registers();
-        save_state(&(consumer->saved_state),
-                subgoal->generator_maxfr, subgoal->generator_sp,
-                "suspension", "consumer");
-        MR_restore_transient_registers();
-
-        cur_gen = MR_gen_next - 1;
-        cur_cut = MR_cut_next - 1;
-        stop_addr = consumer->saved_state.non_stack_block_start;
-        for (fr = MR_maxfr; fr > stop_addr; fr = MR_prevfr_slot(fr))
-        {
-                offset = MR_redoip_addr(fr) -
-                        consumer->saved_state.non_stack_block_start;
-                clobber_addr = consumer->saved_state.non_stack_block + offset;
-#if 0
-                if (MR_tablestackdebug) {
-                        printf("redoip addr ");
-                        MR_printnondstackptr(MR_redoip_addr(fr));
-                        printf(", offset %d from start, ", offset);
-                        printf("saved copy at %p\n", clobber_addr);
-                }
-#endif
-
-                if (fr == MR_gen_stack[cur_gen].generator_frame) {
-                        if (MR_gen_stack[cur_gen].generator_table->MR_subgoal
-                                        == subgoal)
-                        {
-                                /*
-                                ** This is the nondet stack frame of the
-                                ** generator corresponding to this consumer.
-                                */
-
-                                assert(MR_prevfr_slot(fr) == (stop_addr - 1));
-                                *clobber_addr = (MR_Word)
-                                        MR_ENTRY(mercury__table_builtin__table_nondet_resume_1_0);
-#ifdef  MR_TABLE_DEBUG
-                                if (MR_tablestackdebug) {
-                                        printf("completing redoip "
-                                                "of frame at ");
-                                        MR_printnondstackptr(fr);
-                                        printf(" (in saved copy)\n");
-                                }
-#endif
-
-                                consumer->saved_state.gen_next = cur_gen + 1;
-#ifdef  MR_TABLE_DEBUG
-                                if (MR_tabledebug) {
-                                        printf("saved gen_next set to %d\n",
-                                                cur_gen + 1);
-                                }
-#endif
-                        } else {
-                                /*
-                                ** This is the nondet stack frame of some
-                                ** other generator.
-                                */
-
-                                assert(MR_prevfr_slot(fr) != (stop_addr - 1));
-
-                                *clobber_addr = (MR_Word) MR_ENTRY(MR_do_fail);
-#ifdef  MR_TABLE_DEBUG
-                                if (MR_tablestackdebug) {
-                                        printf("clobbering redoip "
-                                                "of frame at ");
-                                        MR_printnondstackptr(fr);
-                                        printf(" (in saved copy)\n");
-                                }
-#endif
-
-                                MR_save_transient_registers();
-                                make_subgoal_follow_leader(
-                                        MR_gen_stack[cur_gen].
-                                                generator_table->MR_subgoal,
-                                        subgoal);
-                                MR_restore_transient_registers();
-                        }
-
-                        cur_gen--;
-                } else if (cur_cut > 0 && fr == MR_cut_stack[cur_cut].frame) {
-                        *clobber_addr = (MR_Word) MR_ENTRY(MR_table_nondet_commit);
-#ifdef  MR_TABLE_DEBUG
-                        if (MR_tablestackdebug) {
-                                printf("committing redoip of frame at ");
-                                MR_printnondstackptr(fr);
-                                printf(" (in saved copy)\n");
-                        }
-#endif
-
-                        cur_cut--;
-                } else {
-                        *clobber_addr = (MR_Word) MR_ENTRY(MR_do_fail);
-#ifdef  MR_TABLE_DEBUG
-                        if (MR_tablestackdebug) {
-                                printf("clobbering redoip of frame at ");
-                                MR_printnondstackptr(fr);
-                                printf(" (in saved copy)\n");
-                        }
-#endif
-                }
-        }
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("adding suspension node %p to table %p",
-                        consumer, subgoal);
-                printf(" at slot %p\n", subgoal->consumer_list_tail);
-        }
-#endif
-
-        assert(*(subgoal->consumer_list_tail) == NULL);
-        listnode = MR_table_allocate_bytes(sizeof(MR_ConsumerListNode));
-        *(subgoal->consumer_list_tail) = listnode;
-        subgoal->consumer_list_tail = &(listnode->next);
-        listnode->item = consumer;
-        listnode->next = NULL;
-}
-        MR_fail();
-MR_END_MODULE
-
-MR_Subgoal      *MR_cur_leader;
-
-/*
-** The procedure defined below restores answers to suspended consumers.
-** It works by restoring the consumer state saved by the consumer's call
-** to table_nondet_suspend. By restoring such states and then returning
-** answers, table_nondet_resume is essentially returning answers out of
-** the call to table_nondet_suspend, not out of the call to
-** table_nondet_resume.
-**
-** The code is arranged as a three level iteration to a fixpoint.
-** The three levels are: iterating over all subgoals in a connected component,
-** iterating over all consumers of each of those subgoals, and iterating
-** over all the answers to be returned to each of those consumers.
-** Note that returning an answer could lead to further answers for
-** any of the subgoals in the connected component; it can even lead
-** to the expansion of the component (i.e. the addition of more subgoals
-** to it).
-*/
-
-MR_define_extern_entry(mercury__table_builtin__table_nondet_resume_1_0);
-MR_declare_label(mercury__table_builtin__table_nondet_resume_1_0_ChangeLoop);
-MR_declare_label(mercury__table_builtin__table_nondet_resume_1_0_ReachedFixpoint);
-MR_declare_label(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions);
-MR_declare_label(mercury__table_builtin__table_nondet_resume_1_0_ReturnAnswer);
-MR_declare_label(mercury__table_builtin__table_nondet_resume_1_0_RedoPoint);
-
-MR_MAKE_PROC_LAYOUT(mercury__table_builtin__table_nondet_resume_1_0,
-        MR_DETISM_NON, MR_PROC_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN,
-        MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_ChangeLoop,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_ReachedFixpoint,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_LoopOverSubgoals,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_ReturnAnswer,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_RedoPoint,
-        mercury__table_builtin__table_nondet_resume_1_0);
-MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
-        mercury__table_builtin__table_nondet_resume_1_0_RestartPoint,
-        mercury__table_builtin__table_nondet_resume_1_0);
-
-MR_BEGIN_MODULE(table_nondet_resume_module)
-        MR_init_entry_sl(mercury__table_builtin__table_nondet_resume_1_0);
-        MR_INIT_PROC_LAYOUT_ADDR(mercury__table_builtin__table_nondet_resume_1_0);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_ChangeLoop);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_ReachedFixpoint);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSubgoals);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_ReturnAnswer);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_RedoPoint);
-        MR_init_label_sl(mercury__table_builtin__table_nondet_resume_1_0_RestartPoint);
-MR_BEGIN_CODE
-
-MR_define_entry(mercury__table_builtin__table_nondet_resume_1_0);
-        MR_cur_leader = MR_top_generator_table();
-
-        if (MR_cur_leader->leader != NULL) {
-                /*
-                ** The predicate that called table_nondet_resume
-                ** is not the leader of its component.
-                ** We will leave all answers to be returned
-                ** by the leader.
-                */
-
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("non-leader table_nondet_resume fails\n");
-                }
-#endif
-
-                (void) MR_pop_generator();
-                MR_redo();
-        }
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("table_nondet_resume enter: current leader is %p\n",
-                        MR_cur_leader);
-        }
-#endif
-
-        if (MR_cur_leader->resume_info != NULL) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("using existing resume info %p\n",
-                                MR_cur_leader->resume_info);
-                }
-#endif
-        } else {
-                MR_cur_leader->resume_info = MR_TABLE_NEW(MR_ResumeInfo);
-
-                MR_save_transient_registers();
-                save_state(&(MR_cur_leader->resume_info->leader_state),
-                        MR_cur_leader->generator_maxfr,
-                        MR_cur_leader->generator_sp,
-                        "resumption", "generator");
-                MR_restore_transient_registers();
-
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("creating new resume info %p\n",
-                                MR_cur_leader->resume_info);
-                }
-#endif
-        }
-
-        MR_cur_leader->resume_info->changed = MR_TRUE;
-
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_ChangeLoop);
-
-        if (MR_cur_leader->resume_info->changed) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("changed flag set\n");
-                }
+	num_inputs = proc->MR_sle_table_info.MR_table_gen->
+		MR_table_gen_num_inputs;
+	num_outputs = proc->MR_sle_table_info.MR_table_gen->
+		MR_table_gen_num_outputs;
+
+	ptis = proc->MR_sle_table_info.MR_table_gen->MR_table_gen_ptis;
+	ptis += num_inputs;
+
+	for (i = 0; i < num_outputs; i++) {
+		if (i > 0) {
+			fprintf(fp, ", ");
+		}
+
+		pti = ptis[i];
+		if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(pti)) {
+			fprintf(fp, "poly");
+			continue;
+		}
+
+		tci = MR_PSEUDO_TYPEINFO_GET_TYPE_CTOR_INFO(pti);
+		if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, int, 0)) {
+			fprintf(fp, "%ld", (long) answer_block[i]);
+		} else if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, float, 0)) {
+			fprintf(fp, "%f",
+#ifdef	MR_HIGHLEVEL_CODE
+				(double) MR_unbox_float(
+						(MR_Box) answer_block[i]));
+#else
+				(double) MR_word_to_float(answer_block[i]));
 #endif
+		} else if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, string, 0)) {
+			fprintf(fp, "\"%s\"", (char *) answer_block[i]);
         } else {
-                MR_SubgoalList  table_list;
-
-                for (table_list = MR_cur_leader->resume_info->subgoal_list;
-                        table_list != NULL; table_list = table_list->next)
-                {
-                        if (table_list->item->num_committed_ans
-                                != table_list->item->num_ans)
-                        {
-                                MR_cur_leader->resume_info->changed = MR_TRUE;
-#ifdef  MR_TABLE_DEBUG
-                                if (MR_tabledebug) {
-                                        printf("table %p has new answers\n",
-                                                table_list->item);
-                                }
-#endif
-                        }
-                }
-        }
-
-        if (! MR_cur_leader->resume_info->changed) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("no more changes\n");
-                }
-#endif
-                MR_GOTO_LABEL(
-                        mercury__table_builtin__table_nondet_resume_1_0_ReachedFixpoint);
+			fprintf(fp, "value of unsupported type");
         }
-
-        MR_cur_leader->resume_info->subgoal_list = MR_cur_leader->followers;
-
-        /* For each of the subgoals on our list of followers */
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSubgoals);
-
-        if (MR_cur_leader->resume_info->subgoal_list == NULL) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("no more subgoals in the followers list\n");
-                }
-#endif
-
-                MR_GOTO_LABEL(mercury__table_builtin__table_nondet_resume_1_0_ChangeLoop);
-        }
-
-        MR_cur_leader->resume_info->cur_subgoal =
-                MR_cur_leader->resume_info->subgoal_list->item;
-        MR_cur_leader->resume_info->subgoal_list =
-                MR_cur_leader->resume_info->subgoal_list->next;
-
-        MR_cur_leader->resume_info->consumer_list =
-                MR_cur_leader->resume_info->cur_subgoal->consumer_list;
-
-        MR_cur_leader->resume_info->changed = MR_FALSE;
-        MR_cur_leader->resume_info->cur_subgoal->num_committed_ans =
-                MR_cur_leader->resume_info->cur_subgoal->num_ans;
-
-        /* For each of the suspended nodes for cur_subgoal */
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions);
-
-        if (MR_cur_leader->resume_info->consumer_list == NULL) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("no more suspensions for current subgoal\n");
                 }
-#endif
-                MR_GOTO_LABEL(
-                        mercury__table_builtin__table_nondet_resume_1_0_LoopOverSubgoals);
-        }
-
-        MR_cur_leader->resume_info->cur_consumer =
-                MR_cur_leader->resume_info->consumer_list->item;
-        MR_cur_leader->resume_info->consumer_list =
-                MR_cur_leader->resume_info->consumer_list->next;
-
-        MR_cur_leader->resume_info->cur_consumer_answer_list =
-                *(MR_cur_leader->resume_info->cur_consumer->
-                        remaining_answer_list_ptr);
-
-        if (MR_cur_leader->resume_info->cur_consumer_answer_list == NULL) {
-#ifdef  MR_TABLE_DEBUG
-                if (MR_tabledebug) {
-                        printf("no first answer for this suspension\n");
-                }
-#endif
-                MR_GOTO_LABEL(
-                        mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions);
-        }
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("resuming consumer %p from table %p\n",
-                        (void *) MR_cur_leader->resume_info->cur_consumer,
-                        (void *) MR_cur_leader->resume_info->cur_subgoal);
-        }
-#endif
-
-        MR_save_transient_registers();
-        restore_state(
-                &(MR_cur_leader->resume_info->cur_consumer->saved_state),
-                "resumption", "consumer");
-        MR_restore_transient_registers();
-
-        /* check that there is room for exactly one framevar */
-        assert((MR_maxfr - MR_prevfr_slot(MR_maxfr)) ==
-                (MR_NONDET_FIXED_SIZE + 1));
-
-        MR_gen_next = MR_cur_leader->resume_info->leader_state.gen_next;
-        MR_redoip_slot(MR_maxfr) =
-                MR_LABEL(mercury__table_builtin__table_nondet_resume_1_0_RedoPoint);
-        MR_redofr_slot(MR_maxfr) = MR_maxfr;
-        MR_based_framevar(MR_maxfr, 1) = (MR_Word) MR_cur_leader;
-
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_ReturnAnswer);
-
-        /*
-        ** Return the next answer in MR_cur_leader->resume_info->
-        ** cur_consumer_answer_list to the current consumer. Since we have
-        ** already restored the context of the suspended consumer before
-        ** we returned the first answer, we don't need to restore it again,
-        ** since will not have changed in the meantime.
-        */
-
-        MR_r1 = (MR_Word) &MR_cur_leader->resume_info->
-                cur_consumer_answer_list->answer_data;
-
-        MR_cur_leader->resume_info->cur_consumer->remaining_answer_list_ptr =
-                &(MR_cur_leader->resume_info->cur_consumer_answer_list->
-                next_answer);
-
-        MR_cur_leader->resume_info->cur_consumer_answer_list =
-                MR_cur_leader->resume_info->cur_consumer_answer_list->
-                next_answer;
-
-        /*
-        ** Return the answer. Since we just restored the state of the
-        ** computation that existed when suspend was called, the code
-        ** that we return to is the code following the call to suspend.
-        */
-        MR_succeed();
-
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_RedoPoint);
-        MR_update_prof_current_proc(MR_LABEL(mercury__table_builtin__table_nondet_resume_1_0));
-
-        /*
-        ** This is where the current consumer suspension will go on
-        ** backtracking when it wants the next solution. If there is a solution
-        ** we haven't returned to this consumer yet, we do so, otherwise we
-        ** remember how many answers we have returned to this consumer so far
-        ** and move on to the next suspended consumer of the current subgoal.
-        */
-
-        MR_cur_leader = (MR_Subgoal *) MR_based_framevar(MR_maxfr, 1);
-
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_RestartPoint);
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("cur_consumer_answer_list: %p\n",
-                        MR_cur_leader->resume_info->cur_consumer_answer_list);
-                printf("*cur_consumer->remaining_answer_list_ptr: %p\n",
-                        *(MR_cur_leader->resume_info->cur_consumer->
-                                remaining_answer_list_ptr));
-        }
-#endif
-
-        if (MR_cur_leader->resume_info->cur_consumer_answer_list != NULL) {
-                MR_GOTO_LABEL(mercury__table_builtin__table_nondet_resume_1_0_ReturnAnswer);
-        }
-
-#ifdef  MR_TABLE_DEBUG
-        if (MR_tabledebug) {
-                printf("no more unreturned answers for this suspension\n");
-        }
-#endif
-
-        if (MR_cur_leader->resume_info->cur_subgoal->num_committed_ans
-                != MR_cur_leader->resume_info->cur_subgoal->num_ans)
-        {
-                MR_cur_leader->resume_info->changed = MR_TRUE;
-        }
-
-        MR_GOTO_LABEL(mercury__table_builtin__table_nondet_resume_1_0_LoopOverSuspensions);
-
-MR_define_label(mercury__table_builtin__table_nondet_resume_1_0_ReachedFixpoint);
-        {
-                MR_SubgoalList  table_list;
-
-                for (table_list = MR_cur_leader->followers;
-                        table_list != NULL; table_list = table_list->next)
-                {
-#ifdef  MR_TABLE_DEBUG
-                        if (MR_tabledebug) {
-                                printf("marking table %p complete\n",
-                                        table_list->item);
-                        }
-#endif
-
-                        table_list->item->status = MR_SUBGOAL_COMPLETE;
-                        table_list->item->num_committed_ans = -1;
-                }
-        }
-
-        /* Restore the state we had when table_nondet_resume was called */
-        MR_save_transient_registers();
-        restore_state(&(MR_cur_leader->resume_info->leader_state),
-                "resumption", "generator");
-        MR_restore_transient_registers();
-
-        /* XXX we should free this cell and its components */
-        MR_cur_leader->resume_info = NULL;
-
-        /* We are done with this generator */
-        (void) MR_pop_generator();
-
-        MR_proceed();
-MR_END_MODULE
-
-MR_define_extern_entry(MR_table_nondet_commit);
-MR_BEGIN_MODULE(table_nondet_commit_module)
-        MR_init_entry_an(MR_table_nondet_commit);
-MR_BEGIN_CODE
-MR_define_entry(MR_table_nondet_commit);
-        MR_commit_cut();
-        MR_fail();
-MR_END_MODULE
-
-#endif /* ! MR_HIGHLEVEL_CODE */
-
-#endif  /* MR_USE_MINIMAL_MODEL */
-
-#ifdef MR_HIGHLEVEL_CODE
-
-/*
-** We need to define stubs for these, even if MR_USE_MINIMAL_MODEL
-** is not enabled, since they are declared as `:- external', and
-** hence for profiling grades the generated code will take their
-** address to store in the label table.
-*/
-
-/* Declare them first, to avoid warnings from gcc -Wmissing-decls */
-void MR_CALL mercury__table_builtin__table_nondet_resume_1_p_0(
-        MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
-        MR_Cont cont, void *cont_env_ptr);
-void MR_CALL mercury__table_builtin__table_nondet_suspend_2_p_0(
-        MR_C_Pointer subgoal_table_node);
-
-void MR_CALL
-mercury__table_builtin__table_nondet_resume_1_p_0(
-        MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
-        MR_Cont cont, void *cont_env_ptr)
-{
-        MR_fatal_error("sorry, not implemented: "
-                "minimal model tabling with --high-level-code");
 }
 
-void MR_CALL
-mercury__table_builtin__table_nondet_suspend_2_p_0(
-        MR_C_Pointer subgoal_table_node)
-{
-        MR_fatal_error("sorry, not implemented: "
-                "minimal model tabling with --high-level-code");
-}
-
-#endif /* MR_HIGHLEVEL_CODE */
-
-/* Ensure that the initialization code for the above modules gets to run. */
-/*
-INIT mercury_sys_init_table_modules
-*/
-
-#ifdef  MR_USE_MINIMAL_MODEL
-MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_nondet_suspend_module;
-MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_nondet_resume_module;
-MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_nondet_commit_module;
-#endif
-
-/* forward declarations to suppress gcc -Wmissing-decl warnings */
-void mercury_sys_init_table_modules_init(void);
-void mercury_sys_init_table_modules_init_type_tables(void);
-#ifdef  MR_DEEP_PROFILING
-void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp);
-#endif
-
-void mercury_sys_init_table_modules_init(void)
-{
-#ifdef  MR_USE_MINIMAL_MODEL
-        table_nondet_suspend_module();
-        table_nondet_resume_module();
-        table_nondet_commit_module();
-#endif
-}
-
-void mercury_sys_init_table_modules_init_type_tables(void)
-{
-        /* no types to register */
-}
-
-#ifdef  MR_DEEP_PROFILING
-void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp)
-{
-        /* no proc_statics to write out */
-}
-#endif
+/*---------------------------------------------------------------------------*/
Index: runtime/mercury_tabling.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_tabling.h,v
retrieving revision 1.29
diff -u -b -r1.29 mercury_tabling.h
--- runtime/mercury_tabling.h	15 Nov 2002 04:50:41 -0000	1.29
+++ runtime/mercury_tabling.h	10 Mar 2003 08:24:51 -0000
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1997-2000,2002 The University of Melbourne.
+** Copyright (C) 1997-2000,2002-2003 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
@@ -20,6 +20,8 @@
 #include "mercury_float.h"
 #include "mercury_reg_workarounds.h"
 #include "mercury_dlist.h"
+#include "mercury_goto.h"		/* for MR_declare_entry */
+#include "mercury_stack_layout.h"	/* for MR_Proc_Layout */
 
 #ifndef MR_CONSERVATIVE_GC
   #include "mercury_deep_copy.h"
@@ -30,22 +32,6 @@
 /*---------------------------------------------------------------------------*/
 
 /*
-** Forward declarations of type names.
-*/
-
-typedef	struct MR_HashTable_Struct		MR_HashTable;
-typedef	struct MR_Subgoal_Struct		MR_Subgoal;
-typedef	struct MR_SubgoalListNode_Struct	MR_SubgoalListNode;
-typedef	struct MR_AnswerListNode_Struct		MR_AnswerListNode;
-typedef	struct MR_ConsumerListNode_Struct	MR_ConsumerListNode;
-
-typedef	MR_SubgoalListNode			*MR_SubgoalList;
-typedef	MR_AnswerListNode			*MR_AnswerList;
-typedef	MR_ConsumerListNode			*MR_ConsumerList;
-
-/*---------------------------------------------------------------------------*/
-
-/*
 ** Tabling builds up two kinds of tables, both conceptually tries. For call
 ** tables, there is one layer in the trie for each input argument; for answer
 ** tables, there is one layer in the trie for each output argument. However,
@@ -149,122 +135,6 @@
 	MR_SUBGOAL_COMPLETE
 } MR_SubgoalStatus;
 
-struct MR_AnswerListNode_Struct {
-	MR_Integer	answer_num;
-	MR_TableNode	answer_data; /* always uses the MR_answerblock member */
-	MR_AnswerList	next_answer;
-};
-
-/*
-** The saved state of a generator or a consumer. While consumers get
-** suspended while they are waiting for generators to produce more solutions,
-** generators need their state saved when they restore the state of a consumer
-** to consume a new solution.
-**
-** The saved state contains copies of
-**
-** - several virtual machine registers:
-**   MR_succip, MR_sp, MR_curfr and MR_maxfr
-**
-** - segments of the nondet and det stacks:
-**   the parts that cannot possibly change between the times of saving
-**   and restoring the saved state are not saved.
-**
-**   The segments are described by three fields each. The *_block_start
-**   field gives the address of the first word in the real stack
-**   that is part of the saved segment, the *_block_size field
-**   gives the size of the saved segment in words, and the *_block
-**   field points to the area of memory containing the saved segment.
-**
-** - the entire generator stack and the entire cut stack:
-**   they are usually so small, it is faster to save them all
-**   than to figure out which parts need saving.
-**
-**   Each stack is described by its size in words and a pointer to
-**   an area of memory containing the entire saved stack.
-*/
-
-typedef struct {
-	MR_Code			*succ_ip;
-	MR_Word			*s_p;
-	MR_Word			*cur_fr;
-	MR_Word			*max_fr;
-	MR_Word			*non_stack_block_start;
-	MR_Word			non_stack_block_size;
-	MR_Word			*non_stack_block;
-	MR_Word			*det_stack_block_start;
-	MR_Word			det_stack_block_size;
-	MR_Word			*det_stack_block;
-	MR_Integer		gen_next;
-	char			*generator_stack_block;
-	MR_Integer		cut_next;
-	char			*cut_stack_block;
-} MR_SavedState;
-
-/* The state of a consumer subgoal */
-typedef struct {
-	MR_SavedState		saved_state;
-	MR_AnswerList		*remaining_answer_list_ptr;
-} MR_Consumer;
-
-struct MR_ConsumerListNode_Struct {
-	MR_Consumer		*item;
-	MR_ConsumerList		next;
-};
-
-/*
-** The following structure is used to hold the state and variables used in 
-** the table_resume procedure.
-*/
-
-typedef struct {
-	MR_SavedState		leader_state;
-	MR_SubgoalList		subgoal_list;
-	MR_Subgoal		*cur_subgoal;
-	MR_ConsumerList		consumer_list;	/* for the current subgoal */
-	MR_Consumer		*cur_consumer;
-	MR_AnswerList		cur_consumer_answer_list;
-	MR_bool			changed;
-} MR_ResumeInfo;
-
-struct MR_SubgoalListNode_Struct {
-	MR_Subgoal		*item;
-	MR_SubgoalList		next;
-};
-
-/* Used to save info about a single subgoal in the table */
-struct MR_Subgoal_Struct {
-	MR_SubgoalStatus	status;
-	MR_Subgoal		*leader;
-	MR_SubgoalList		followers;
-	MR_SubgoalList		*followers_tail;
-	MR_ResumeInfo		*resume_info;
-	MR_Word			answer_table;	/* Table of answers returned */
-						/* by the subgoal */
-	MR_Integer		num_ans;	/* # of answers returned */
-						/* by the subgoal */
-	MR_Integer		num_committed_ans;
-						/* # of answers our leader */
-						/* is committed to returning */
-						/* to every consumer. */
-	MR_AnswerList		answer_list;	/* List of answers returned */
-						/* by the subgoal */
-	MR_AnswerList		*answer_list_tail;
-						/* Pointer to the tail of */
-						/* the answer list. This is */
-						/* used to update the tail. */
-	MR_ConsumerList		consumer_list;	/* List of suspended calls */
-						/* to the subgoal */
-	MR_ConsumerList		*consumer_list_tail;
-						/* As for answer_list_tail */
-	MR_Word			*generator_maxfr;
-						/* MR_maxfr at the time of */
-						/* the call to the generator */
-	MR_Word			*generator_sp;
-						/* MR_sp at the time of the */
-						/* call to the generator */
-};
-
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -362,6 +232,14 @@
 
 extern	void		MR_table_report_statistics(FILE *fp);
 
+/*
+** Prints the given answer_block of the given procedure to fp.
+*/
+extern	void		MR_print_answerblock(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_Word *answer_block);
+
+
 /*---------------------------------------------------------------------------*/
 
 #ifndef MR_NATIVE_GC
@@ -375,17 +253,30 @@
   #define MR_TABLE_RESIZE_ARRAY(ptr, type, count)			\
 	MR_GC_RESIZE_ARRAY((ptr), type, (count))
 
+#if 0
   #define MR_table_allocate_bytes(size)					\
 	MR_GC_malloc((size))
 
   #define MR_table_reallocate_bytes(pointer, size)			\
 	MR_GC_realloc((pointer), (size))
+#endif
 
   #define MR_table_allocate_words(size)					\
-	MR_GC_malloc(sizeof(MR_Word) * (size))
+	((MR_Word *) MR_GC_malloc(sizeof(MR_Word) * (size)))
 
   #define MR_table_reallocate_words(pointer, size)			\
-	MR_GC_realloc((pointer), sizeof(MR_Word) * (size))
+	(MR_CHECK_EXPR_TYPE((pointer), MR_Word *),			\
+	(MR_Word *) MR_GC_realloc((pointer), sizeof(MR_Word) * (size)))
+
+  #define MR_table_allocate_struct(type)				\
+	((type *) MR_GC_malloc(sizeof(type)))
+
+  #define MR_table_allocate_structs(num, type)				\
+	((type *) MR_GC_malloc(sizeof(type) * (num)))
+
+  #define MR_table_reallocate_structs(pointer, num, type)		\
+	(MR_CHECK_EXPR_TYPE((pointer), type *),				\
+	(type *) MR_GC_realloc((pointer), sizeof(type) * (num)))
 
   #define MR_table_free(pointer)					\
 	MR_GC_free((pointer))
@@ -407,18 +298,29 @@
   #define MR_TABLE_RESIZE_ARRAY(pointer, type, count)			\
 	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG),			\
 	(void *) NULL)
+#if 0
   #define MR_table_allocate_bytes(size)					\
 	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG),			\
 	(void *) NULL)
   #define MR_table_reallocate_bytes(pointer, size)			\
 	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG),			\
 	(void *) NULL)
+#endif
   #define MR_table_allocate_words(size)					\
 	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG), 			\
 	(void *) NULL)
   #define MR_table_reallocate_words(pointer, size)			\
 	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG), 			\
 	(void *) NULL)
+  #define MR_table_allocate_struct(type)				\
+	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG), 			\
+	(void *) NULL)
+  #define MR_table_allocate_structs(num, type)				\
+	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG), 			\
+	(void *) NULL)
+  #define MR_table_reallocate_structs(pointer, num, type)		\
+	(MR_fatal_error(MR_TABLE_NATIVE_GC_MSG), 			\
+	(void *) NULL)
   #define MR_table_free(pointer)					\
 	MR_fatal_error(MR_TABLE_NATIVE_GC_MSG)
   #define MR_table_list_cons(h, t)					\
@@ -431,7 +333,16 @@
 	MR_memcpy((dest), (source), (size))
 
 #define MR_table_copy_words(dest, source, size)				\
-	MR_memcpy((char *) (dest), (char *) (source), sizeof(MR_Word) * (size))
+	(MR_CHECK_EXPR_TYPE((dest), MR_Word *),				\
+	(MR_CHECK_EXPR_TYPE((source), MR_Word *),			\
+	MR_memcpy((char *) (dest), (char *) (source),			\
+		sizeof(MR_Word) * (size))))
+
+#define MR_table_copy_structs(dest, source, num, type)			\
+	(MR_CHECK_EXPR_TYPE((dest), type *),				\
+	(MR_CHECK_EXPR_TYPE((source), type *),				\
+	MR_memcpy((char *) (dest), (char *) (source),			\
+		sizeof(type) * (num))))
 
 /*---------------------------------------------------------------------------*/
 
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.31
diff -u -b -r1.31 mercury_trace_base.h
--- runtime/mercury_trace_base.h	8 Nov 2002 08:48:21 -0000	1.31
+++ runtime/mercury_trace_base.h	18 Nov 2002 04:19:47 -0000
@@ -19,6 +19,7 @@
 #include "mercury_stack_layout.h"
 #include "mercury_std.h"
 #include "mercury_tabling.h"	/* for MR_TableNode */
+#include "mercury_goto.h"	/* for MR_declare_entry */
 
 /*
 ** This enum should EXACTLY match the definition of the `trace_port_type'
@@ -345,5 +346,12 @@
 			int *histogram, int max);
 
 #endif	/* MR_TRACE_HISTOGRAM */
+
+#ifndef	MR_HIGHLEVEL_CODE
+
+MR_declare_entry(MR_do_trace_redo_fail_shallow);
+MR_declare_entry(MR_do_trace_redo_fail_deep);
+
+#endif	/* !MR_HIGHLEVEL_CODE */
 
 #endif /* MERCURY_TRACE_BASE_H */
Index: runtime/mercury_types.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_types.h,v
retrieving revision 1.30
diff -u -b -r1.30 mercury_types.h
--- runtime/mercury_types.h	15 Nov 2002 04:50:41 -0000	1.30
+++ runtime/mercury_types.h	10 Mar 2003 08:28:42 -0000
@@ -135,6 +135,25 @@
 typedef union MR_TableNode_Union                MR_TableNode;
 typedef MR_TableNode                            *MR_TrieNode;
 
+typedef struct MR_HashTable_Struct              MR_HashTable;
+typedef struct MR_Subgoal_Struct                MR_Subgoal;
+typedef struct MR_SubgoalListNode_Struct        MR_SubgoalListNode;
+typedef struct MR_AnswerListNode_Struct         MR_AnswerListNode;
+typedef struct MR_ConsumerListNode_Struct       MR_ConsumerListNode;
+
+typedef MR_SubgoalListNode                      *MR_SubgoalList;
+typedef MR_AnswerListNode                       *MR_AnswerList;
+typedef MR_ConsumerListNode                     *MR_ConsumerList;
+
+typedef struct MR_GenStackFrameStruct           MR_GenStackFrame;
+typedef struct MR_CutStackFrameStruct           MR_CutStackFrame;
+typedef struct MR_PNegStackFrameStruct          MR_PNegStackFrame;
+
+typedef struct MR_PNegConsumerListNodeStruct    MR_PNegConsumerListNode;
+typedef MR_PNegConsumerListNode                 *MR_PNegConsumerList;
+
+/*---------------------------------------------------------------------------*/
+
 /*
 ** The MR_Box type is used for representing polymorphic types.
 ** Currently this is only used in the MLDS C backend.
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.117
diff -u -b -r1.117 mercury_wrapper.c
--- runtime/mercury_wrapper.c	3 Mar 2003 16:30:44 -0000	1.117
+++ runtime/mercury_wrapper.c	7 Mar 2003 04:23:41 -0000
@@ -68,8 +68,9 @@
 size_t		MR_global_heap_size =		1024;
 size_t		MR_trail_size =			 128;
 size_t		MR_debug_heap_size =		4096;
-size_t		MR_generatorstack_size =	  32;
+size_t		MR_genstack_size =		  32;
 size_t		MR_cutstack_size =		  32;
+size_t		MR_pnegstack_size =		  32;
 
 /* size of the redzones at the end of data areas, in kilobytes */
 /* (but we later multiply by 1024 to convert to bytes) */
@@ -80,8 +81,9 @@
 size_t		MR_global_heap_zone_size =	  16;
 size_t		MR_trail_zone_size =		  16;
 size_t		MR_debug_heap_zone_size =	  16;
-size_t		MR_generatorstack_zone_size =	  16;
+size_t		MR_genstack_zone_size =		  16;
 size_t		MR_cutstack_zone_size =		  16;
+size_t		MR_pnegstack_zone_size =	  16;
 
 /*
 ** MR_heap_margin_size is used for accurate GC with the MLDS->C back-end.
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.56
diff -u -b -r1.56 mercury_wrapper.h
--- runtime/mercury_wrapper.h	8 Nov 2002 00:45:49 -0000	1.56
+++ runtime/mercury_wrapper.h	7 Dec 2002 13:41:22 -0000
@@ -190,8 +190,9 @@
 extern	size_t		MR_trail_size;
 extern	size_t		MR_global_heap_size;
 extern	size_t		MR_debug_heap_size;
-extern	size_t		MR_generatorstack_size;
+extern	size_t		MR_genstack_size;
 extern	size_t		MR_cutstack_size;
+extern	size_t		MR_pnegstack_size;
 
 /* sizes of the red zones */
 extern	size_t		MR_heap_zone_size;
@@ -201,8 +202,9 @@
 extern	size_t		MR_trail_zone_size;
 extern	size_t		MR_global_heap_zone_size;
 extern	size_t		MR_debug_heap_zone_size;
-extern	size_t		MR_generatorstack_zone_size;
+extern	size_t		MR_genstack_zone_size;
 extern	size_t		MR_cutstack_zone_size;
+extern	size_t		MR_pnegstack_zone_size;
 
 /* heap margin for MLDS->C accurate GC (documented in mercury_wrapper.c) */
 extern	size_t		MR_heap_margin_size;
cvs diff: Diffing runtime/GETOPT
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 samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/all_solutions.exp3
===================================================================
RCS file: tests/debugger/all_solutions.exp3
diff -N tests/debugger/all_solutions.exp3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/all_solutions.exp3	11 Mar 2003 04:13:50 -0000
@@ -0,0 +1,22 @@
+       1:      1  1 CALL pred all_solutions.main/2-0 (det) all_solutions.m:16
+mdb> echo on
+Command echo enabled.
+mdb> context none
+Contexts will not be printed.
+mdb> register --quiet
+mdb> break hello
+ 0: + stop  interface pred all_solutions.hello/1-0 (multi)
+mdb> continue
+       2:      2  2 CALL pred all_solutions.hello/1-0 (multi)
+mdb> stack
+   0       pred all_solutions.hello/1-0 (multi)
+reached label with no stack layout info.
+mdb> retry 1
+reached label with no stack layout info
+mdb> retry 2
+reached label with no stack layout info
+mdb> retry 3
+reached label with no stack layout info
+mdb> continue -n -S
+Hello again, world
+Hello, world
Index: tests/debugger/exception_value.exp3
===================================================================
RCS file: tests/debugger/exception_value.exp3
diff -N tests/debugger/exception_value.exp3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/exception_value.exp3	11 Mar 2003 03:28:40 -0000
@@ -0,0 +1,42 @@
+      E1:     C1  1 CALL pred exception_value.main/2-0 (cc_multi) exception_value.m:12
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred exception_value.p/1-0 (det)
+mdb> break q
+ 1: + stop  interface pred exception_value.q/1-0 (det)
+mdb> continue
+      E2:     C2  3 CALL pred exception_value.p/1-0 (det) exception_value.m:30
+mdb> finish
+      E3:     C2  3 EXCP pred exception_value.p/1-0 (det)
+mdb> print exception
+	"p exception"
+mdb> continue
+mdb: warning: reached unknown label
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons("p exception"))
+      E4:     C3  3 CALL pred exception_value.q/1-0 (det) exception_value.m:35
+mdb> finish
+      E5:     C3  3 EXCP pred exception_value.q/1-0 (det)
+mdb> browse exception
+browser> set depth 9
+browser> set size 99
+browser> ls
+-
+1-"q oops"
+2-[|]
+  1-1
+  2-[|]
+    1-2
+    2-[|]
+      1-3
+      2-[]
+
+browser> quit
+mdb> continue
+mdb: warning: reached unknown label
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons("q oops" - [1, 2, 3]))
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.23
diff -u -b -r1.23 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	11 Mar 2003 02:44:24 -0000	1.23
+++ tests/debugger/mdb_command_test.inp	11 Mar 2003 02:54:07 -0000
@@ -45,7 +45,10 @@
 histogram_all        xyzzy xyzzy xyzzy xyzzy xyzzy
 histogram_exp        xyzzy xyzzy xyzzy xyzzy xyzzy
 clear_histogram      xyzzy xyzzy xyzzy xyzzy xyzzy
+subgoal              xyzzy xyzzy xyzzy xyzzy xyzzy
 gen_stack            xyzzy xyzzy xyzzy xyzzy xyzzy
+cut_stack            xyzzy xyzzy xyzzy xyzzy xyzzy
+pneg_stack           xyzzy xyzzy xyzzy xyzzy xyzzy
 nondet_stack         xyzzy xyzzy xyzzy xyzzy xyzzy
 stack_regs           xyzzy xyzzy xyzzy xyzzy xyzzy
 all_regs             xyzzy xyzzy xyzzy xyzzy xyzzy
cvs diff: Diffing tests/debugger/declarative
Index: tests/debugger/declarative/catch.exp3
===================================================================
RCS file: tests/debugger/declarative/catch.exp3
diff -N tests/debugger/declarative/catch.exp3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/catch.exp3	10 Mar 2003 10:35:01 -0000
@@ -0,0 +1,40 @@
+       1:      1  1 CALL pred catch.main/2-0 (cc_multi) catch.m:8
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred catch.p/2-0 (cc_multi)
+mdb> continue
+       2:      2  2 CALL pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:9)
+mdb> finish
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+       7:      2  2 EXIT pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:9)
+mdb> dd
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+p(1, exception(univ_cons("q: bad input")))
+Valid? no
+Sorry, the diagnosis cannot continue because it requires support for
+the following: code that catches exceptions.
+The debugger is a work in progress, and this is not supported in the
+current version.
+       7:      2  2 EXIT pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:9)
+mdb> continue
+exception(univ_cons("q: bad input"))
+       8:      4  2 CALL pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:12)
+mdb> finish
+      13:      4  2 EXIT pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:12)
+mdb> dd
+p(2, succeeded(2))
+Valid? no
+q(2, 2)
+Valid? yes
+Found incorrect contour:
+p(2, succeeded(2))
+Is this a bug? yes
+      13:      4  2 EXIT pred catch.p/2-0 (cc_multi) catch.m:18 (catch.m:12)
+mdb> continue
+succeeded(2)
Index: tests/debugger/declarative/ho5.exp3
===================================================================
RCS file: tests/debugger/declarative/ho5.exp3
diff -N tests/debugger/declarative/ho5.exp3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/ho5.exp3	10 Mar 2003 10:36:02 -0000
@@ -0,0 +1,48 @@
+       1:      1  1 CALL pred ho5.main/2-0 (cc_multi) ho5.m:8
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred ho5.p/2-0 (det)
+mdb> continue
+       2:      2  2 CALL pred ho5.p/2-0 (det) ho5.m:18
+mdb> finish
+       9:      2  2 EXCP pred ho5.p/2-0 (det) c2; ho5.m:18
+mdb> dd
+Call p(1, _)
+Throws zero
+Expected? no
+q(1, 0)
+Valid? yes
+Call r(0, _)
+Throws zero
+Expected? yes
+Found unhandled exception:
+p(1, _)
+zero
+Is this a bug? yes
+       9:      2  2 EXCP pred ho5.p/2-0 (det) c2; ho5.m:18
+mdb> continue
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons('<<function>>'))
+      10:      5  2 CALL pred ho5.p/2-0 (det) ho5.m:18
+mdb> finish
+      17:      5  2 EXCP pred ho5.p/2-0 (det) c2; ho5.m:18
+mdb> dd
+Call p(2, _)
+Throws zero
+Expected? no
+q(2, 0)
+Valid? yes
+Found unhandled exception:
+p(2, _)
+zero
+Is this a bug? yes
+      17:      5  2 EXCP pred ho5.p/2-0 (det) c2; ho5.m:18
+mdb> continue
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons('<<function>>'))
Index: tests/debugger/declarative/throw.exp3
===================================================================
RCS file: tests/debugger/declarative/throw.exp3
diff -N tests/debugger/declarative/throw.exp3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/throw.exp3	10 Mar 2003 10:37:25 -0000
@@ -0,0 +1,53 @@
+       1:      1  1 CALL pred throw.main/2-0 (cc_multi) throw.m:10
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred throw.p/1-0 (cc_nondet)
+mdb> break q
+ 1: + stop  interface pred throw.q/1-0 (semidet)
+mdb> continue
+       2:      2  2 CALL pred throw.p/1-0 (cc_nondet) throw.m:20
+mdb> finish
+      31:      2  2 EXCP pred throw.p/1-0 (cc_nondet)
+mdb> dd
+Call p(_)
+Throws "Too big"
+Expected? no
+a(3)
+Valid? yes
+Call b(3, _)
+Throws "Too big"
+Expected? yes
+Found unhandled exception:
+p(_)
+"Too big"
+Is this a bug? yes
+      31:      2  2 EXCP pred throw.p/1-0 (cc_nondet)
+mdb> continue
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons("Too big"))
+      32:      6  2 CALL pred throw.q/1-0 (semidet) throw.m:48
+mdb> finish
+      65:      6  2 EXCP pred throw.q/1-0 (semidet)
+mdb> dd
+Call q(_)
+Throws "Too big"
+Expected? no
+a2(3)
+Valid? yes
+Call b2(3, _)
+Throws "Too big"
+Expected? yes
+Found unhandled exception:
+q(_)
+"Too big"
+Is this a bug? yes
+      65:      6  2 EXCP pred throw.q/1-0 (semidet)
+mdb> continue
+mdb: warning: reached label with no stack layout info
+This may result in some exception events
+being omitted from the trace.
+exception(univ_cons("Too big"))
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
Index: tests/tabling/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/tabling/Mmakefile,v
retrieving revision 1.18
diff -u -b -r1.18 Mmakefile
--- tests/tabling/Mmakefile	30 Oct 2002 01:42:18 -0000	1.18
+++ tests/tabling/Mmakefile	12 Mar 2003 05:14:49 -0000
@@ -24,6 +24,7 @@
 	coup_no_commit \
 	coup_non_tabled_frame \
 	generator_in_commit \
+	mday \
 	repeat \
 	seq \
 	tc_loop \
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.59
diff -u -b -r1.59 mercury_trace.c
--- trace/mercury_trace.c	6 Nov 2002 02:02:37 -0000	1.59
+++ trace/mercury_trace.c	12 Mar 2003 08:18:12 -0000
@@ -440,6 +440,12 @@
     /* This also saves the regs in MR_fake_regs. */
     MR_copy_regs_to_saved_regs(event_info.MR_max_mr_num, saved_regs);
 
+#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_TABLE_DEBUG)
+    if (port == MR_PORT_CALL) {
+        MR_subgoal_debug_cur_proc = layout->MR_sll_entry;
+    }
+#endif
+
 #ifdef MR_USE_EXTERNAL_DEBUGGER
     if (MR_trace_handler == MR_TRACE_EXTERNAL) {
         if (!interactive) {
@@ -1247,8 +1253,8 @@
         trienode = (MR_TrieNode) MR_based_framevar(cur_maxfr, 
                     proc_layout->MR_sle_maybe_call_table);
         subgoal = trienode->MR_subgoal;
-        if (subgoal->leader != NULL) {
-            leader = subgoal->leader;
+        if (subgoal->MR_sg_leader != NULL) {
+            leader = subgoal->MR_sg_leader;
         } else {
             leader = subgoal;
         }
@@ -1261,7 +1267,7 @@
         record_ptrs[record_ptr_next].found_leader_generator = MR_FALSE;
         record_ptr_next++;
 
-        if (cur_maxfr == MR_gen_stack[cur_gen].generator_frame) {
+        if (cur_maxfr == MR_gen_stack[cur_gen].MR_generator_frame) {
             for (i = 0; i < record_ptr_next; i++) {
                 if (record_ptrs[i].record_leader == subgoal) {
                     record_ptrs[i].found_leader_generator = MR_TRUE;
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.153
diff -u -b -r1.153 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	11 Mar 2003 02:56:35 -0000	1.153
+++ trace/mercury_trace_internal.c	13 Mar 2003 06:31:32 -0000
@@ -533,9 +533,24 @@
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 			MR_Event_Details *event_details, MR_Code **jumpaddr);
 
+static MR_Next	MR_trace_cmd_flag(char **words, int word_count,
+			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+			MR_Event_Details *event_details, MR_Code **jumpaddr);
+static MR_Next	MR_trace_cmd_subgoal(char **words, int word_count,
+			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+			MR_Event_Details *event_details, MR_Code **jumpaddr);
+static MR_Next	MR_trace_cmd_consumer(char **words, int word_count,
+			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+			MR_Event_Details *event_details, MR_Code **jumpaddr);
 static MR_Next	MR_trace_cmd_gen_stack(char **words, int word_count,
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 			MR_Event_Details *event_details, MR_Code **jumpaddr);
+static MR_Next	MR_trace_cmd_cut_stack(char **words, int word_count,
+			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+			MR_Event_Details *event_details, MR_Code **jumpaddr);
+static MR_Next	MR_trace_cmd_pneg_stack(char **words, int word_count,
+			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+			MR_Event_Details *event_details, MR_Code **jumpaddr);
 
 static MR_Next	MR_trace_cmd_nondet_stack(char **words, int word_count,
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
@@ -682,10 +697,14 @@
 /* Prints the given subgoal of the given procedure to MR_mdb_out. */
 static	void	MR_trace_print_subgoal(const MR_Proc_Layout *proc,
 			MR_Subgoal *subgoal);
+static	void	MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
+			MR_SubgoalDebug *subgoal_debug);
 
-/* Prints the given answer_block of the given procedure to MR_mdb_out. */
-static	void	MR_print_answerblock(const MR_Proc_Layout *proc,
-			MR_Word *answer_block);
+/* Prints the given consumer of the given procedure to MR_mdb_out. */
+static	void	MR_trace_print_consumer(const MR_Proc_Layout *proc,
+			MR_Consumer *consumer);
+static	void	MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
+			MR_ConsumerDebug *consumer_debug);
 
 static	void	MR_trace_set_level_and_report(int ancestor_level,
 			MR_bool detailed, MR_bool print_optionals);
@@ -722,6 +741,8 @@
 static	char	*MR_trace_command_completer_next(const char *word,
 			size_t word_len, MR_Completer_Data *data);
 
+static	MR_bool	MR_saved_tabledebug;
+
 MR_Code *
 MR_trace_event_internal(MR_Trace_Cmd_Info *cmd, MR_bool interactive,
 		MR_Event_Info *event_info)
@@ -730,7 +751,6 @@
 	char			*line;
 	MR_Next			res;
 	MR_Event_Details	event_details;
-	MR_bool			saved_tabledebug;
 
 	if (! interactive) {
 		return MR_trace_event_internal_report(cmd, event_info);
@@ -748,7 +768,7 @@
 	*/
 
 	MR_trace_enabled = MR_FALSE;
-	saved_tabledebug = MR_tabledebug;
+	MR_saved_tabledebug = MR_tabledebug;
 	MR_tabledebug = MR_FALSE;
 	MR_saved_io_tabling_enabled = MR_io_tabling_enabled;
 	MR_io_tabling_enabled = MR_FALSE;
@@ -792,7 +812,7 @@
 
 	MR_scroll_next = 0;
 	MR_trace_enabled = MR_TRUE;
-	MR_tabledebug = saved_tabledebug;
+	MR_tabledebug = MR_saved_tabledebug;
 	MR_io_tabling_enabled = MR_saved_io_tabling_enabled;
 	return jumpaddr;
 }
@@ -3266,6 +3286,140 @@
 }
 
 static MR_Next
+MR_trace_cmd_flag(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+	const char	*name;
+	MR_bool		*flagptr;
+	int		i;
+	MR_bool		found;
+
+	if (word_count >= 2) {
+		name = words[1];
+	} else {
+		MR_trace_usage("developer", "flag");
+		return KEEP_INTERACTING;
+	}
+
+	found = MR_FALSE;
+	for (i = 0; i < MR_MAXFLAG; i++) {
+		if (MR_streq(MR_debug_flag_info[i].MR_debug_flag_name, name)) {
+			flagptr = &MR_debugflag[
+				MR_debug_flag_info[i].MR_debug_flag_index];
+
+			if (flagptr == &MR_tabledebug) {
+				/*
+				** The true value of MR_tabledebug is stored
+				** in MR_saved_tabledebug inside the call tree
+				** of MR_trace_event.
+				*/
+				flagptr = &MR_saved_tabledebug;
+			}
+
+			found = MR_TRUE;
+			break;
+		}
+	}
+
+	if (!found) {
+		fprintf(MR_mdb_out, "There is no flag named %s.\n", name);
+		return KEEP_INTERACTING;
+	}
+
+	if (word_count == 2) {
+		if (*flagptr) {
+			fprintf(MR_mdb_out, "Flag %s is set.\n", name);
+		} else {
+			fprintf(MR_mdb_out, "Flag %s is clear.\n", name);
+		}
+	} else if (word_count == 3) {
+		if (MR_streq(words[2], "on")) {
+			*flagptr = MR_TRUE;
+			fprintf(MR_mdb_out, "Flag %s is now set.\n", name);
+		} else if (MR_streq(words[2], "off")) {
+			*flagptr = MR_FALSE;
+			fprintf(MR_mdb_out, "Flag %s is now clear.\n", name);
+		} else {
+			MR_trace_usage("developer", "flag");
+		}
+	} else {
+		MR_trace_usage("developer", "flag");
+	}
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Next
+MR_trace_cmd_subgoal(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+
+	MR_SubgoalDebug	*subgoal_debug;
+	MR_Subgoal	*subgoal;
+	int		n;
+
+	if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+		MR_trace_init_modules();
+
+		subgoal_debug = MR_lookup_subgoal_debug_num(n);
+		if (subgoal_debug == NULL) {
+			fprintf(MR_mdb_out, "no such subgoal\n");
+		} else {
+			MR_trace_print_subgoal_debug(NULL, subgoal_debug);
+		}
+	} else {
+		MR_trace_usage("developer", "subgoal");
+	}
+
+#else	/* MR_USE_MINIMAL_MODEL */
+
+	fprintf(MR_mdb_out, "mdb: the `subgoal' command is available "
+		"only in minimal model tabling grades.\n");
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Next
+MR_trace_cmd_consumer(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+
+	MR_ConsumerDebug	*consumer_debug;
+	MR_Consumer		*consumer;
+	int			n;
+
+	if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+		MR_trace_init_modules();
+
+		consumer_debug = MR_lookup_consumer_debug_num(n);
+		if (consumer_debug == NULL) {
+			fprintf(MR_mdb_out, "no such consumer\n");
+		} else {
+			MR_trace_print_consumer_debug(NULL, consumer_debug);
+		}
+	} else {
+		MR_trace_usage("developer", "consumer");
+	}
+
+#else	/* MR_USE_MINIMAL_MODEL */
+
+	fprintf(MR_mdb_out, "mdb: the `consumer' command is available "
+		"only in minimal model tabling grades.\n");
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+	return KEEP_INTERACTING;
+}
+
+
+static MR_Next
 MR_trace_cmd_gen_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
@@ -3295,6 +3449,64 @@
 }
 
 static MR_Next
+MR_trace_cmd_cut_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+
+	if (word_count == 1) {
+		MR_bool	saved_tabledebug;
+
+		MR_trace_init_modules();
+		saved_tabledebug = MR_tabledebug;
+		MR_tabledebug = MR_TRUE;
+		MR_print_cut_stack(MR_mdb_out);
+		MR_tabledebug = saved_tabledebug;
+	} else {
+		MR_trace_usage("developer", "cut_stack");
+	}
+
+#else	/* MR_USE_MINIMAL_MODEL */
+
+	fprintf(MR_mdb_out, "mdb: the `cut_stack' command is available "
+		"only in minimal model grades.\n");
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Next
+MR_trace_cmd_pneg_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+
+	if (word_count == 1) {
+		MR_bool	saved_tabledebug;
+
+		MR_trace_init_modules();
+		saved_tabledebug = MR_tabledebug;
+		MR_tabledebug = MR_TRUE;
+		MR_print_pneg_stack(MR_mdb_out);
+		MR_tabledebug = saved_tabledebug;
+	} else {
+		MR_trace_usage("developer", "pneg_stack");
+	}
+
+#else	/* MR_USE_MINIMAL_MODEL */
+
+	fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
+		"only in minimal model grades.\n");
+
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Next
 MR_trace_cmd_nondet_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
@@ -4294,7 +4506,7 @@
 				break;
 			default:
 				fprintf(MR_mdb_out, "succeeded <");
-				MR_print_answerblock(proc,
+				MR_print_answerblock(MR_mdb_out, proc,
 					table->MR_answerblock);
 				fprintf(MR_mdb_out, ">\n");
 				break;
@@ -4319,56 +4531,43 @@
 static void
 MR_trace_print_subgoal(const MR_Proc_Layout *proc, MR_Subgoal *subgoal)
 {
-	fprintf(MR_mdb_out, "cannot print subgoals yet\n");
+#ifdef	MR_USE_MINIMAL_MODEL
+	MR_print_subgoal(MR_mdb_out, proc, subgoal);
+#else
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
 }
 
 static void
-MR_print_answerblock(const MR_Proc_Layout *proc, MR_Word *answer_block)
+MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
+	MR_SubgoalDebug *subgoal_debug)
 {
-	const MR_PseudoTypeInfo	*ptis;
-	MR_PseudoTypeInfo	pti;
-	MR_TypeCtorInfo		tci;
-	int			num_inputs;
-	int			num_outputs;
-	int			i;
-
-	num_inputs = proc->MR_sle_table_info.MR_table_gen->
-		MR_table_gen_num_inputs;
-	num_outputs = proc->MR_sle_table_info.MR_table_gen->
-		MR_table_gen_num_outputs;
-
-	ptis = proc->MR_sle_table_info.MR_table_gen->MR_table_gen_ptis;
-	ptis += num_inputs;
-
-	for (i = 0; i < num_outputs; i++) {
-		if (i > 0) {
-			fprintf(MR_mdb_out, ", ");
-		}
+#ifdef	MR_USE_MINIMAL_MODEL
+	MR_print_subgoal_debug(MR_mdb_out, proc, subgoal_debug);
+#else
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
 
-		pti = ptis[i];
-		if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(pti)) {
-			fprintf(MR_mdb_out, "poly");
-			continue;
-		}
+static void
+MR_trace_print_consumer(const MR_Proc_Layout *proc, MR_Consumer *consumer)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+	MR_print_consumer(MR_mdb_out, proc, consumer);
+#else
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
 
-		tci = MR_PSEUDO_TYPEINFO_GET_TYPE_CTOR_INFO(pti);
-		if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, int, 0)) {
-			fprintf(MR_mdb_out, "%ld", (long) answer_block[i]);
-		} else if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, float, 0)) {
-			fprintf(MR_mdb_out, "%f",
-#ifdef	MR_HIGHLEVEL_CODE
-				(double) MR_unbox_float(
-						(MR_Box) answer_block[i]));
+static void
+MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
+	MR_ConsumerDebug *consumer_debug)
+{
+#ifdef	MR_USE_MINIMAL_MODEL
+	MR_print_consumer_debug(MR_mdb_out, proc, consumer_debug);
 #else
-				(double) MR_word_to_float(answer_block[i]));
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
 #endif
-		} else if (tci == &MR_TYPE_CTOR_INFO_NAME(builtin, string, 0)) {
-			fprintf(MR_mdb_out, "\"%s\"",
-				(char *) answer_block[i]);
-		} else {
-			fprintf(MR_mdb_out, "value of unsupported type");
-		}
-	}
 }
 
 static MR_Next
@@ -6218,7 +6417,17 @@
 	{ "exp", "clear_histogram", MR_trace_cmd_clear_histogram,
 		NULL, MR_trace_null_completer },
 
+	{ "developer", "flag", MR_trace_cmd_flag,
+		NULL, MR_trace_null_completer },
+	{ "developer", "subgoal", MR_trace_cmd_subgoal,
+		NULL, MR_trace_null_completer },
+	{ "developer", "consumer", MR_trace_cmd_consumer,
+		NULL, MR_trace_null_completer },
 	{ "developer", "gen_stack", MR_trace_cmd_gen_stack,
+		NULL, MR_trace_null_completer },
+	{ "developer", "cut_stack", MR_trace_cmd_cut_stack,
+		NULL, MR_trace_null_completer },
+	{ "developer", "pneg_stack", MR_trace_cmd_pneg_stack,
 		NULL, MR_trace_null_completer },
 	{ "developer", "nondet_stack", MR_trace_cmd_nondet_stack,
 		MR_trace_stack_cmd_args, MR_trace_null_completer },
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list