[m-rev.] diff: more minimal model improvements

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Mar 12 17:01:30 AEDT 2004


More improvements for minimal model tabling.

runtime/mercury_engine.[ch]:
	Provide a debug flag to control the printing of debug stack slots
	in nondet stack dumps.

runtime/mercury_stack_trace.[ch]:
	Provide a mechanism that allows a dump of the nondet stack to print
	the principal debugging stack slots of the stack frames of procedures
	that were compiled with debugging, to help debug problems where
	these are overwritten during stack segment saves/restores.

	Add a mechanism for limiting the output of a nondet stack trace
	to a segment of the nondet stack.

runtime/mercury_minimal_model.[ch]:
	Limit the output of a diagnostic nondet stack trace to just the
	segment being saved or restored.

	Provide a label layout structure for the entry point of the suspend
	predicate, since this is necessary for correct nondet stack traces
	at suspensions and resumptions.

	Store the layout structure of the top nondet stack frame with each
	saved state, to allow the saved nondet stack segment to be dumped
	at resumptions as well as suspensions.

	Fix an old bug: when extending a saved stack segment, use the same
	algorithm for determining its lower bound as when the stack segment
	was created in the first place.

	Factor out some repeated definitions.

	Note problems to be fixed later.

	Improve debugging output.

runtime/mercury_stacks.[ch]:
	Move the documentation of the generator stack, the cut stack and the
	pneg stack from the source file to the header file, and expand it
	considerably.

	Make the routines for printing entries of these stacks generate more
	consistently formatted output.

	Simplify some code.

runtime/mercury_stack_layout.h:
	Provide a macro for use by mercury_minimal_model.c.

runtime/mercury_trace_base.[ch]:
	Save and restore the global variables holding event numbers,
	call sequence numbers and call depths across debugging Mercury code.
	We already used to do this for Mercury code invoked by the debugger,
	but now that we can invoke Mercury code to print the values of
	variables as diagnostics from within the suspend and resume predicates
	*outside* the debugger, we need to do it more generally.

trace/mercury_trace.c:
	Fix a bug: provide the layout structure of the current procedure
	to the diagnostic routines for minimal model tabling even if the
	debugger doesn't stop at that procedure.

trace/mercury_trace_internal.c:
	Add two new mdb commands to help debug minimal model tabling.

	The "mm_stack" command has the same effect as the existing commands
	"gen_stack", "cut_stack" and "pneg_stack" executed in sequence.

	The "debug_vars" command prints the counters for event numbers,
	call sequence numbers and call depths, both from their global variables
	and their saved copies, for debugging problems where they are
	overwritten, such as the one fixed by the changes to
	mercury_trace_base.[ch] above.

	Reorder some code for consistency.

trace/mercury_trace_util.[ch]:
	Add a function to implement the "debug_vars" command.

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

doc/mdb_categories:
	Add the new mdb commands to the list of developer commands, as well
	some others previously left out.

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

tests/tabling/combine.m:
	Change the code of this test case to what was intended, so that it now
	matches the old expected output.

tests/tabling/completed_consumer_in_solutions.{m,exp}:
	New test case, an easier version of consumer_in_solutions.

tests/tabling/consumer_in_commit.{m,exp}:
	Extend this test case and update the expected output; we can execute
	both the original code and the extension without runtime exceptions.

tests/tabling/seq2.m:
	Fix Kostis's new test case.

tests/tabling/seq4.exp:
	Fix the expected output of Kostis's new test case.

tests/tabling/Mmakefile:
	Enable the new test cases, and some old test cases that we now pass.

Zoltan.

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
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/mdb_categories
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/mdb_categories,v
retrieving revision 1.18
diff -u -b -r1.18 mdb_categories
--- doc/mdb_categories	7 Nov 2003 04:33:19 -0000	1.18
+++ doc/mdb_categories	12 Mar 2004 02:17:58 -0000
@@ -67,9 +67,10 @@
 document_category 1100 developer
 developer  - Commands that are intended to be of use only to developers
              of the Mercury implementation. The developer commands are
-             `nondet_stack', `stack_regs', `all_regs', `proc_stats',
-             `label_stats', `print_optionals', `unhide_events', `dd_dd',
-             `table', `type_ctor', `class_decl', `all_type_ctors' and
-	     `all_class_decls'.
+             `flag', `subgoal', `consumer', `gen_stack', `cut_stack,
+             `pneg_stack', `mm_stacks', `nondet_stack', `stack_regs',
+             `all_regs', `debug_vars', `proc_stats', `label_stats',
+             `print_optionals', `unhide_events', `dd_dd', `table',
+             `type_ctor', `class_decl', `all_type_ctors' and `all_class_decls'.
 
 end
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.381
diff -u -b -r1.381 user_guide.texi
--- doc/user_guide.texi	19 Feb 2004 00:18:20 -0000	1.381
+++ doc/user_guide.texi	11 Mar 2004 16:33:35 -0000
@@ -3268,6 +3268,13 @@
 prints the contents of the frames on the possible negated context stack.
 In other grades, it reports an error.
 @sp 1
+ at item mm_stacks
+ at kindex mm_stacks (mdb command)
+In minimal model grades,
+prints the contents of the frames on the generator stack,
+the cut stack and the possible negated context stack.
+In other grades, it reports an error.
+ at sp 1
 @item nondet_stack [-d] [@var{num}]
 @kindex nondet_stack (mdb command)
 Prints the contents of the frames on the nondet stack.
@@ -3286,6 +3293,11 @@
 @item all_regs
 @kindex all_regs (mdb command)
 Prints the contents of all the virtual machine registers.
+ at sp 1
+ at item debug_vars
+ at kindex debug_vars (mdb command)
+Prints the values of the variables used by the debugger
+to record event numbers, call sequence numbers and call depths.
 @sp 1
 @item proc_stats
 @kindex proc_stats (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/error
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/moose/tests
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
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.45
diff -u -b -r1.45 mercury_engine.c
--- runtime/mercury_engine.c	24 Oct 2003 03:09:51 -0000	1.45
+++ runtime/mercury_engine.c	11 Mar 2004 16:27:25 -0000
@@ -62,6 +62,7 @@
 	{ "printlocn",	MR_PRINT_LOCN_FLAG },
 	{ "enabled",	MR_LLD_DEBUG_ENABLED_FLAG },
 	{ "notnearest",	MR_NOT_NEAREST_FLAG },
+	{ "debugslots",	MR_DEBUG_SLOTS_FLAG },
 	{ "detail",	MR_DETAILFLAG }
 };
 
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.32
diff -u -b -r1.32 mercury_engine.h
--- runtime/mercury_engine.h	1 Jun 2003 06:52:35 -0000	1.32
+++ runtime/mercury_engine.h	11 Mar 2004 16:27:25 -0000
@@ -63,8 +63,9 @@
 #define	MR_PRINT_LOCN_FLAG 		17
 #define	MR_LLD_DEBUG_ENABLED_FLAG 	18
 #define	MR_NOT_NEAREST_FLAG 		19
-#define	MR_DETAILFLAG			20
-#define	MR_MAXFLAG			21
+#define	MR_DEBUG_SLOTS_FLAG		20
+#define	MR_DETAILFLAG			21
+#define	MR_MAXFLAG			22
 /* MR_DETAILFLAG should be the last real flag */
 
 /*
@@ -125,6 +126,10 @@
 ** MR_not_nearest_flag, if set, tells minimal model tabling to save stack
 ** segments only to the nearest generator, not to the nearest common ancestor
 ** of the consumer being suspended and its generator.
+**
+** MR_debug_slots_flag controls whether dumps of nondet stack frames will
+** print the values of the fixed stack slots used by the debugger, in the
+** stack frames of procedures compiled with debugging.
 */
 
 #define	MR_progdebug		MR_debugflag[MR_PROGFLAG]
@@ -147,6 +152,7 @@
 #define	MR_printlocndebug	MR_debugflag[MR_PRINT_LOCN_FLAG]
 #define	MR_lld_debug_enabled	MR_debugflag[MR_LLD_DEBUG_ENABLED_FLAG]
 #define	MR_not_nearest_flag	MR_debugflag[MR_NOT_NEAREST_FLAG]
+#define	MR_debug_slots_flag	MR_debugflag[MR_DEBUG_SLOTS_FLAG]
 #define	MR_detaildebug		MR_debugflag[MR_DETAILFLAG]
 
 typedef struct {
Index: runtime/mercury_minimal_model.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.c,v
retrieving revision 1.5
diff -u -b -r1.5 mercury_minimal_model.c
--- runtime/mercury_minimal_model.c	10 Mar 2004 04:30:38 -0000	1.5
+++ runtime/mercury_minimal_model.c	12 Mar 2004 04:03:07 -0000
@@ -24,7 +24,7 @@
 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,
-                    MR_bool can_print_stack_detail);
+                    const MR_Label_Layout *top_layout);
 static  void    restore_state(MR_SavedState *saved_state, const char *who,
                     const char *what);
 static  void    extend_consumer_stacks(MR_Subgoal *leader,
@@ -407,6 +407,7 @@
 ** suspensions and resumptions of derivations.
 */
 
+#define SUSPEND_LABEL(name) MR_PASTE3(MR_SUSPEND_ENTRY, _, name)
 #define RESUME_LABEL(name)  MR_PASTE3(MR_RESUME_ENTRY, _, name)
 
 /*
@@ -458,7 +459,7 @@
 
 static void
 save_state(MR_SavedState *saved_state, MR_Word *generator_fr,
-    const char *who, const char *what, MR_bool can_print_stack_detail)
+    const char *who, const char *what, const MR_Label_Layout *top_layout)
 {
     MR_Word *common_ancestor_fr;
     MR_Word *start_non;
@@ -467,6 +468,11 @@
     MR_restore_transient_registers();
 
     if (MR_not_nearest_flag) {
+        /*
+        ** This can yield incorrect results, as documented in mday_sld.tex
+        ** in papers/tabling2. It is included here only to allow demonstrations
+        ** of *why* this is incorrect.
+        */
         common_ancestor_fr = generator_fr;
     } else {
         common_ancestor_fr = nearest_common_ancestor(MR_curfr, generator_fr);
@@ -479,6 +485,7 @@
     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;
+    saved_state->MR_ss_top_layout = top_layout;
 
     /* we copy from start_non to MR_maxfr, both inclusive */
     saved_state->MR_ss_non_stack_real_start = start_non;
@@ -533,12 +540,8 @@
     }
 
     if (MR_tablestackdebug) {
-        if (can_print_stack_detail) {
-            MR_dump_nondet_stack_from_layout(stdout, 0, MR_maxfr,
-                MR_subgoal_debug_cur_proc->MR_sle_call_label, MR_sp, MR_curfr);
-        } else {
-            MR_dump_nondet_stack(stdout, 0, MR_maxfr);
-        }
+        MR_dump_nondet_stack_from_layout(stdout, start_non, 0, MR_maxfr,
+            top_layout, MR_sp, MR_curfr);
     }
   #endif /* MR_TABLE_DEBUG */
 
@@ -589,8 +592,9 @@
     }
 
     if (MR_tablestackdebug) {
-        MR_dump_nondet_stack_from_layout(stdout, 0, MR_maxfr, NULL,
-            MR_sp, MR_curfr);
+        MR_dump_nondet_stack_from_layout(stdout,
+            saved_state->MR_ss_non_stack_real_start, 0, MR_maxfr,
+            saved_state->MR_ss_top_layout, MR_sp, MR_curfr);
     }
   #endif /* MR_TABLE_DEBUG */
 
@@ -604,8 +608,9 @@
 ** 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.
+** nca(consumer, B) will in general be lower than nca(consumer, A)
+** (where nca = nearest common ancestor). The consumer's saved state
+** goes down to nca(consumer, A); we need to extend it to nca(consumer, B).
 */
 
 static void
@@ -615,6 +620,7 @@
     MR_Word         *arena_start;
     MR_Word         arena_size;
     MR_Word         extension_size;
+    MR_Word         *old_common_ancestor_fr;
     MR_Word         *new_common_ancestor_fr;
     MR_Word         *saved_fr;
     MR_Word         *real_fr;
@@ -624,30 +630,50 @@
 
     cons_saved_state = &consumer->MR_cns_saved_state;
 
+    old_common_ancestor_fr = cons_saved_state->MR_ss_common_ancestor_fr;
+    new_common_ancestor_fr = nearest_common_ancestor(old_common_ancestor_fr,
+        leader->MR_sg_generator_fr);
+
 #ifdef  MR_TABLE_DEBUG
-    if (MR_tablestackdebug) {
-        printf("\nextending saved consumer stacks\n");
+    if (MR_tabledebug) {
+        printf("extending saved state of consumer %s for %s\n",
+            MR_consumer_addr_name(consumer), MR_subgoal_addr_name(leader));
+        printf("common ancestors: old ");
+        MR_printnondstackptr(old_common_ancestor_fr);
+        printf(", new ");
+        MR_printnondstackptr(new_common_ancestor_fr);
+        printf("\nold saved state:\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;
+    arena_start = MR_table_detfr_slot(new_common_ancestor_fr) + 1;
     extension_size = cons_saved_state->MR_ss_det_stack_real_start
         - arena_start;
+
+    if (extension_size > 0) {
     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);
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("assert: det arena_start ");
+            MR_printdetstackptr(arena_start);
+            printf(" + %d = ", arena_size);
+            MR_printdetstackptr(cons_saved_state->MR_ss_s_p);
+            printf(" + 1: diff %d\n",
+                (arena_start + arena_size)
+                - (cons_saved_state->MR_ss_s_p + 1));
     }
 #endif
 
+        if (arena_size != 0) {
+            assert(arena_start + arena_size
+                == cons_saved_state->MR_ss_s_p + 1);
+        }
+
     arena_block = MR_table_allocate_words(arena_size);
 
     MR_table_copy_words(arena_block, arena_start, extension_size);
@@ -671,17 +697,32 @@
     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;
+    arena_start = MR_prevfr_slot(new_common_ancestor_fr) + 1;
     extension_size = cons_saved_state->MR_ss_non_stack_real_start
         - arena_start;
+    if (extension_size > 0) {
     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);
+#ifdef  MR_TABLE_DEBUG
+        if (MR_tabledebug) {
+            printf("assert: non arena_start ");
+            MR_printnondstackptr(arena_start);
+            printf(" + %d = ", arena_size);
+            MR_printnondstackptr(cons_saved_state->MR_ss_max_fr);
+            printf(" + 1: diff %d\n",
+                (arena_start + arena_size)
+                - (cons_saved_state->MR_ss_max_fr + 1));
+        }
 #endif
 
+        if (arena_size != 0) {
+            assert(arena_start + arena_size
+                == cons_saved_state->MR_ss_max_fr + 1);
+        }
+
     arena_block = MR_table_allocate_words(arena_size);
 
     MR_table_copy_words(arena_block, arena_start, extension_size);
@@ -705,6 +746,7 @@
     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) {
@@ -713,6 +755,7 @@
     }
 #endif  /* MR_TABLE_DEBUG */
 
+    /* XXX we should be doing this only for the newly added segment */
     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 +
@@ -775,9 +818,8 @@
 
 #ifdef  MR_TABLE_DEBUG
     if (MR_tabledebug) {
-        printf("making %s follow %s\n",
-                MR_subgoal_addr_name(this_follower),
-                MR_subgoal_addr_name(leader));
+        printf("\nmaking %s follow %s\n",
+            MR_subgoal_addr_name(this_follower), MR_subgoal_addr_name(leader));
     }
 #endif  /* MR_TABLE_DEBUG */
 
@@ -936,15 +978,16 @@
 
 #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, -1,
     MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
 MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY, MR_DETISM_NON, 0, -1,
     MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
 
+#ifndef  MR_USE_MINIMAL_MODEL
+
 MR_BEGIN_MODULE(table_nondet_suspend_resume_module)
     MR_init_entry_sl(MR_SUSPEND_ENTRY);
     MR_init_entry_sl(MR_RESUME_ENTRY);
@@ -965,12 +1008,11 @@
 
 MR_Subgoal      *MR_cur_leader;
 
+MR_define_extern_entry(MR_table_nondet_commit);
+
 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));
@@ -979,13 +1021,8 @@
 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, -1,
-    MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
-
-MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY, MR_DETISM_NON, 0, -1,
-    MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+    SUSPEND_LABEL(Call), MR_SUSPEND_ENTRY);
 MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
     RESUME_LABEL(ChangeLoop), MR_RESUME_ENTRY);
 MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
@@ -1004,6 +1041,7 @@
 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_label_sl(SUSPEND_LABEL(Call));
 
     MR_init_entry_sl(MR_RESUME_ENTRY);
     MR_INIT_PROC_LAYOUT_ADDR(MR_RESUME_ENTRY);
@@ -1035,6 +1073,16 @@
     ** answers is in table_nondet_resume.
     */
 
+    /*
+    ** 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));
+
+MR_define_label(SUSPEND_LABEL(Call));
 {
     MR_SubgoalPtr   subgoal;
     MR_Consumer     *consumer;
@@ -1048,15 +1096,6 @@
     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));
-
     subgoal = (MR_SubgoalPtr) MR_r1;
     MR_register_suspension(subgoal);
     consumer = MR_table_allocate_struct(MR_Consumer);
@@ -1073,7 +1112,8 @@
 
     MR_save_transient_registers();
     save_state(&(consumer->MR_cns_saved_state), subgoal->MR_sg_generator_fr,
-        "suspension", "consumer", MR_TRUE);
+        "suspension", "consumer",
+        (const MR_Label_Layout *) &MR_LAYOUT_FROM_LABEL(SUSPEND_LABEL(Call)));
     MR_restore_transient_registers();
 
     cur_gen = MR_gen_next - 1;
@@ -1101,27 +1141,39 @@
                 ** 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");
+                    printf("  old contents was %p\n",
+                        (MR_Word *) *clobber_addr);
                 }
   #endif    /* MR_TABLE_DEBUG */
+                *clobber_addr = (MR_Word) MR_ENTRY(MR_RESUME_ENTRY);
 
-                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);
+                    printf("saved gen_next set to %d from %d\n",
+                        cur_gen + 1,
+                        consumer->MR_cns_saved_state.MR_ss_gen_next);
+                    /* XXX if next assignment is not idempotent */
+                    if (consumer->MR_cns_saved_state.MR_ss_gen_next
+                        != cur_gen + 1)
+                    {
+                        MR_print_gen_stack(stdout);
+                        MR_print_cut_stack(stdout);
+                    }
                 }
   #endif    /* MR_TABLE_DEBUG */
+                consumer->MR_cns_saved_state.MR_ss_gen_next = cur_gen + 1;
             } else {
                 /*
                 ** This is the nondet stack frame of some other generator.
                 */
 
   #if 0
+                /* reenable XXX */
                 assert(MR_prevfr_slot(fr) != (stop_addr - 1));
   #endif
 
@@ -1261,7 +1313,7 @@
         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_FALSE);
+            NULL);
         MR_restore_transient_registers();
 
 #ifdef  MR_TABLE_DEBUG
Index: runtime/mercury_minimal_model.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.h,v
retrieving revision 1.3
diff -u -b -r1.3 mercury_minimal_model.h
--- runtime/mercury_minimal_model.h	2 May 2003 21:44:16 -0000	1.3
+++ runtime/mercury_minimal_model.h	11 Mar 2004 08:32:52 -0000
@@ -79,6 +79,9 @@
 
 	MR_Integer		MR_ss_pneg_next;
 	MR_PNegStackFrame	*MR_ss_pneg_stack_saved_block;
+
+	/* to make it possible to generate more detailed debugging output */
+	const MR_Label_Layout	*MR_ss_top_layout;
 } MR_SavedState;
 
 /* The state of a consumer subgoal */
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.74
diff -u -b -r1.74 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h	20 Oct 2003 07:29:32 -0000	1.74
+++ runtime/mercury_stack_layout.h	11 Mar 2004 04:43:01 -0000
@@ -398,9 +398,12 @@
 ** live value information as well to these macros.
 */ 
 
+#define	MR_LAYOUT_FROM_LABEL(label)					\
+	MR_PASTE2(mercury_data__label_layout__, label)
+
 #define MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(label, entry) \
 	MR_Label_Layout_No_Var_Info					\
-	MR_PASTE2(mercury_data__label_layout__, label) = {		\
+	MR_LAYOUT_FROM_LABEL(label) = {					\
 		(MR_Proc_Layout *) &					\
 			MR_PASTE2(mercury_data__proc_layout__, entry),	\
 		-1,							\
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.61
diff -u -b -r1.61 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c	10 Mar 2004 04:30:39 -0000	1.61
+++ runtime/mercury_stack_trace.c	12 Mar 2004 01:58:41 -0000
@@ -302,11 +302,13 @@
 /**************************************************************************/
 
 void
-MR_dump_nondet_stack(FILE *fp, int limit, MR_Word *base_maxfr)
+MR_dump_nondet_stack(FILE *fp, MR_Word *limit_addr, int limit,
+        MR_Word *base_maxfr)
 {
 #ifndef MR_HIGHLEVEL_CODE
 
-    MR_dump_nondet_stack_from_layout(fp, limit, base_maxfr, NULL, NULL, NULL);
+    MR_dump_nondet_stack_from_layout(fp, limit_addr, limit, base_maxfr,
+            NULL, NULL, NULL);
 
 #else   /* !MR_HIGHLEVEL_CODE */
 
@@ -318,8 +320,9 @@
 #ifdef MR_HIGHLEVEL_CODE
 
 void
-MR_dump_nondet_stack_from_layout(FILE *fp, int limit, MR_Word *base_maxfr,
-    const MR_Label_Layout *top_layout, MR_Word *base_sp, MR_Word *base_curfr)
+MR_dump_nondet_stack_from_layout(FILE *fp, MR_Word *limit_addr, int limit,
+    MR_Word *base_maxfr, const MR_Label_Layout *top_layout,
+    MR_Word *base_sp, MR_Word *base_curfr)
 {
     MR_fatal_error("MR_dump_nondet_stack_from_layout in high level grade");
 }
@@ -392,8 +395,9 @@
 #define MR_INIT_NONDET_BRANCH_ARRAY_SIZE        10
 
 void
-MR_dump_nondet_stack_from_layout(FILE *fp, int limit, MR_Word *base_maxfr,
-    const MR_Label_Layout *top_layout, MR_Word *base_sp, MR_Word *base_curfr)
+MR_dump_nondet_stack_from_layout(FILE *fp, MR_Word *limit_addr, int limit,
+    MR_Word *base_maxfr, const MR_Label_Layout *top_layout,
+    MR_Word *base_sp, MR_Word *base_curfr)
 {
     int             frame_size;
     int             level_number;
@@ -401,6 +405,8 @@
     const char      *problem;
     int             frames_traversed_so_far;
     int             branch;
+    const MR_Label_Layout   *label_layout;
+    const MR_Proc_Layout    *proc_layout;
 
     MR_do_init_modules();
 
@@ -431,6 +437,11 @@
             return;
         }
 
+        if (limit_addr != NULL && base_maxfr < limit_addr) {
+            fprintf(fp, "<reached limit of dumped region>\n");
+            return;
+        }
+
         frame_size = base_maxfr - MR_prevfr_slot(base_maxfr);
         if (frame_size == MR_NONDET_TEMP_SIZE) {
             MR_print_nondstackptr(fp, base_maxfr);
@@ -459,8 +470,6 @@
             MR_print_nondstackptr(fp, base_maxfr);
             fprintf(fp, ": ordinary, %d words", frame_size);
             if (print_vars && MR_find_matching_branch(base_maxfr, &branch)) {
-                const MR_Label_Layout *label_layout;
-
                 fprintf(fp, ", ");
                 label_layout = MR_nondet_branch_infos[branch].branch_layout;
                 MR_print_proc_id(fp, label_layout->MR_sll_entry);
@@ -482,6 +491,30 @@
             MR_print_detstackptr(fp, MR_table_detfr_slot(base_maxfr));
             fprintf(fp, "\n");
 #endif
+            if (print_vars && MR_find_matching_branch(base_maxfr, &branch)) {
+                label_layout = MR_nondet_branch_infos[branch].branch_layout;
+                proc_layout = label_layout->MR_sll_entry;
+                if (MR_PROC_LAYOUT_HAS_EXEC_TRACE(proc_layout)
+                    && MR_debug_slots_flag)
+                {
+                    fprintf(fp, " debug:  ");
+                    fprintf(fp, "call event ");
+                    MR_print_nondstackptr(fp,
+                        &MR_event_num_framevar(base_maxfr));
+                    fprintf(fp, " => %d, ",
+                        MR_event_num_framevar(base_maxfr) + 1);
+                    fprintf(fp, "call seq ");
+                    MR_print_nondstackptr(fp,
+                        &MR_call_num_framevar(base_maxfr));
+                    fprintf(fp, " => %d, ",
+                        MR_call_num_framevar(base_maxfr)),
+                    fprintf(fp, "depth ");
+                    MR_print_nondstackptr(fp,
+                        &MR_call_depth_framevar(base_maxfr));
+                    fprintf(fp, " => %d\n",
+                        MR_call_depth_framevar(base_maxfr));
+                }
+            }
 
             level_number++;
             if (print_vars && base_maxfr > MR_nondet_stack_trace_bottom) {
@@ -539,7 +572,7 @@
 
         MR_SavedDebugState  saved_debug_state;
 
-        MR_turn_off_debug(&saved_debug_state);
+        MR_turn_off_debug(&saved_debug_state, MR_TRUE);
         /* XXX we ignore the return value */
         (*MR_address_of_trace_browse_all_on_level) (dump_fp, top_layout,
                 base_sp, base_curfr, level_number, MR_TRUE);
@@ -1124,9 +1157,15 @@
 {
     MR_bool print_details;
 
-    if (base_sp == NULL || base_curfr == NULL) {
+    if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+        if (base_sp == NULL) {
+            return;
+        }
+    } else {
+        if (base_curfr == NULL) {
         return;
     }
+    }
 
     if (MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry)) {
         MR_Integer maybe_from_full = entry->MR_sle_maybe_from_full;
@@ -1166,7 +1205,6 @@
             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) {
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.31
diff -u -b -r1.31 mercury_stack_trace.h
--- runtime/mercury_stack_trace.h	18 Nov 2003 07:02:28 -0000	1.31
+++ runtime/mercury_stack_trace.h	11 Mar 2004 08:25:41 -0000
@@ -77,21 +77,25 @@
 /*
 ** MR_dump_nondet_stack:
 **	This function dumps the control slots of the nondet stack.
+**	If limit_addr is nonnull, dumps only frames above limit_addr.
 **	If limit is nonzero, dumps at most limit frames.
 **	The output format is not meant to be intelligible to non-implementors.
 */
 
-extern	void	MR_dump_nondet_stack(FILE *fp, int limit, MR_Word *maxfr);
+extern	void	MR_dump_nondet_stack(FILE *fp, MR_Word *limit_addr, int limit,
+			MR_Word *maxfr);
 
 /*
 ** MR_dump_nondet_stack_from_layout:
 **	This function dumps the nondet stack.
+**	If limit_addr is nonnull, dumps only frames above limit_addr.
 **	If limit is nonzero, dumps at most limit frames.
 **	The output format is not meant to be intelligible to non-implementors.
 */
 
-extern	void	MR_dump_nondet_stack_from_layout(FILE *fp, int limit,
-			MR_Word *maxfr, const MR_Label_Layout *label_layout,
+extern	void	MR_dump_nondet_stack_from_layout(FILE *fp,
+			MR_Word *limit_addr, int limit, MR_Word *maxfr,
+			const MR_Label_Layout *label_layout,
 			MR_Word *base_sp, MR_Word *base_curfr);
 
 /*
Index: runtime/mercury_stacks.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.c,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_stacks.c
--- runtime/mercury_stacks.c	2 May 2003 21:44:16 -0000	1.10
+++ runtime/mercury_stacks.c	11 Mar 2004 06:10:00 -0000
@@ -6,7 +6,7 @@
 
 /*
 ** This file contains code for printing statistics about stack frame sizes,
-** and for manipulating the generator stack and the cut stack.
+** and for manipulating the generator stack, the cut stack and the pneg stack.
 **
 ** The generator stack has one entry for each call to a minimal model tabled
 ** procedure that is (a) acting as the generator for its subgoal and (b) is
@@ -131,6 +131,11 @@
 
 /***************************************************************************/
 
+/*
+** Record that the nondet stack frame at address frame_addr is now the
+** generator for subgoal.
+*/
+
 void
 MR_push_generator(MR_Word *frame_addr, MR_SubgoalPtr subgoal)
 {
@@ -147,6 +152,10 @@
 #endif
 }
 
+/*
+** Return the subgoal of the topmost generator on the nondet stack.
+*/
+
 MR_Subgoal *
 MR_top_generator_table(void)
 {
@@ -161,6 +170,10 @@
 	return MR_gen_stack[MR_gen_next - 1].MR_gen_subgoal;
 }
 
+/*
+** Record the deletion of the topmost generator on the nondet stack.
+*/
+
 void
 MR_pop_generator(void)
 {
@@ -187,7 +200,7 @@
 {
 	MR_Integer	i;
 
-	fprintf(fp, "gen stack size: %d:\n", (int) gen_next);
+	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]);
 	}
@@ -206,6 +219,10 @@
 
 /***************************************************************************/
 
+/*
+** Record the entering of a committed choice context.
+*/
+
 void
 MR_commit_mark(void)
 {
@@ -227,6 +244,15 @@
 	MR_save_transient_registers();
 }
 
+/*
+** Record the leaving of a committed choice context, and clean up the
+** generators that were created within the context that are still active.
+** We need to clean them up because otherwise, consumers will be depend on this
+** generator to find all the answers to the generator's subgoal, but the
+** generation will never compute any more answers, since it will never be
+** backtracked into.
+*/
+
 void
 MR_commit_cut(void)
 {
@@ -243,13 +269,9 @@
 			(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].MR_cut_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 "
-					"%ld\n",
+				"MR_cut_stack[MR_cut_next].gen_next %ld\n",
 					(long) MR_gen_next,
 					(long) MR_cut_next,
 					(long) MR_cut_stack[MR_cut_next].
@@ -257,7 +279,6 @@
 				MR_fatal_error("GEN_NEXT ASSERTION FAILURE");
 			}
 		}
-	}
 #endif
 
 	for (g = MR_cut_stack[MR_cut_next].MR_cut_generators; g != NULL;
@@ -270,6 +291,11 @@
 	MR_gen_next = MR_cut_stack[MR_cut_next].MR_cut_gen_next;
 }
 
+/*
+** Record the creation of a generator, for possible cleanup later by
+** MR_commit_cut.
+*/
+
 void
 MR_register_generator_ptr(MR_SubgoalPtr subgoal)
 {
@@ -333,7 +359,7 @@
 {
 	MR_Integer	i;
 
-	fprintf(fp, "cut stack size: %d:\n", (int) cut_next);
+	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]);
 	}
@@ -347,9 +373,14 @@
 
 	fprintf(fp, "cut %ld = <", (long) i);
 	MR_print_nondstackptr(fp, p->MR_cut_frame);
-	fprintf(fp, ", %d>:", p->MR_cut_gen_next);
+	fprintf(fp, ">, cut_gen_next %d, ", (int) p->MR_cut_gen_next);
+	fprintf(fp, "pneg+cut stack depth %d\n", (int) p->MR_cut_depth);
 
+	fprintf(fp, "registered generators:");
 	gen_list = p->MR_cut_generators;
+	if (gen_list == NULL) {
+		fprintf(fp, " none");
+	} else {
 	while (gen_list != NULL) {
 		if (gen_list->MR_cut_generator_ptr == NULL) {
 			fprintf(fp, " <NULL>");
@@ -362,6 +393,7 @@
 
 		gen_list = gen_list->MR_cut_next_generator;
 	}
+	}
 
 	fprintf(fp, "\n");
 }
@@ -471,7 +503,7 @@
 void
 MR_print_pneg_stack(FILE *fp)
 {
-	MR_print_pneg_stack_entry(fp, MR_pneg_next, MR_pneg_stack);
+	MR_print_any_pneg_stack(fp, MR_pneg_next, MR_pneg_stack);
 }
 
 void
@@ -480,7 +512,7 @@
 {
 	MR_Integer	i;
 
-	fprintf(fp, "pneg stack size: %d:\n", (int) pneg_next);
+	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]);
 	}
@@ -491,24 +523,26 @@
 {
 	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: ");
+	fprintf(fp, "pneg %d = <", (int) i);
 	MR_print_nondstackptr(fp, p->MR_pneg_frame);
-	fprintf(fp, "\npneg+cut stack depth %d:\n", (int) p->MR_pneg_depth);
+	fprintf(fp, ">, pneg_gen_next %d, ", (int) p->MR_pneg_gen_next);
+	fprintf(fp, "pneg+cut stack depth %d\n", (int) p->MR_pneg_depth);
 
+	fprintf(fp, "registered consumers: ");
 	if (p->MR_pneg_consumers == NULL) {
-		fprintf(fp, "no consumers\n");
+		fprintf(fp, " none");
 	} 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,
+			fprintf(fp, " <%d: %s>", n,
 				MR_subgoal_addr_name(l->MR_pneg_consumer_ptr));
 		}
 	}
+
+	fprintf(fp, "\n");
 }
 
 /***************************************************************************/
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.41
diff -u -b -r1.41 mercury_stacks.h
--- runtime/mercury_stacks.h	5 Nov 2003 08:51:20 -0000	1.41
+++ runtime/mercury_stacks.h	11 Mar 2004 05:56:38 -0000
@@ -468,6 +468,21 @@
 
 /* DEFINITIONS FOR GENERATOR STACK FRAMES */
 
+/*
+** The generator stack has one entry for each call to a minimal model tabled
+** procedure that is (a) acting as the generator for its subgoal and (b) is
+** in the active state. The MR_gen_frame field points to the home nondet stack
+** frame of the generator, and the MR_gen_subgoal field points to the
+** generator's data structure.
+**
+** In systems such as XSB, each choice point has a flag saying whether it is
+** an active generator or not, and if yes, where its subgoal's tabling
+** information is stored. In Mercury, the equivalent test checks whether
+** the generator stack has an entry whose MR_gen_frame field matches the
+** address of the nondet stack frame. This approach that minimizes the
+** performance impact of minimal model evaluation on non-tabled procedures.
+*/
+
 struct MR_GenStackFrameStruct {
 	MR_Word			*MR_gen_frame;
 	MR_SubgoalPtr		MR_gen_subgoal;
@@ -484,6 +499,35 @@
 
 /* DEFINITIONS FOR CUT STACK FRAMES */
 
+/*
+** The cut stack has one entry for each commit goal currently active.
+** (A commit goal is an existential quantification that has a different
+** determinism than the goal being quantified over.) We use the cut stack
+** to prevent generators in the quantified being left active but incomplete
+** when the commit goal succeeds. We need to clean up any such generators
+** because otherwise, consumers will be depend on the generator to find all
+** the answers to the generator's subgoal, but the generator will never
+** compute any more answers, since it will never be backtracked into.
+** The MR_cut_generators field of a cut stack entry contains the list of
+** generators that are inside the corresponding commit and not inside
+** some nested commit.
+**
+** The MR_cut_frame field specifies the address of the nondet stack frame
+** (it should be a temp frame) used by the commit to get control on the
+** failure of the quantified goal. The MR_cut_gen_next field records
+** the value of MR_gen_next (the size of the generator stack) when the
+** commit goal started. When the quantified goal succeeds, the commit cuts
+** away the nondet stack frame at and above MR_cut_frame; we must also throw
+** away the generator stack entries that act as markers on the discarded nondet
+** stack frames. This means the generator stack entries at index
+** MR_cut_gen_next and above.
+**
+** The MR_cut_depth field records the depth of the cut stack entry in
+** the interleaving of the cut stack and pneg stack entries dictated by
+** the nesting of committed choice and possibly negated contexts currently
+** active.
+*/
+
 typedef struct MR_CutGeneratorListNode *MR_CutGeneratorList;
 struct MR_CutGeneratorListNode {
 	MR_SubgoalPtr		MR_cut_generator_ptr;
@@ -507,6 +551,30 @@
 					MR_CutStackFrame *cut_block);
 
 /* DEFINITIONS FOR PNEG STACK FRAMES */
+
+/*
+** The pneg stack has one entry for each possibly negated context currently
+** active. (Possibly negated contexts include the conditions of if-then-elses
+** as well negated goals.) The MR_pneg_consumers field of a pneg stack entry
+** records all the consumers that are inside the corresponding possibly negated
+** context and not inside any nested possibly negated context. When the goal
+** in the possibly negated context fails, we check whether any of these
+** consumers are waiting for more answers from their generator. If yes,
+** then the failure is an artifact of the tabling implementation, and
+** committing to the else branch of the if-then-else or continuing after the
+** negated goal would be incorrect, so we abort the program.
+**
+** The MR_pneg_frame field specifies the address of the nondet stack frame
+** (it should be a temp frame) used by the negation or if-then-else to get
+** control on the failure of the possibly negated goal. The MR_pneg_gen_next
+** field records the value of MR_gen_next (the size of the generator stack)
+** when the possibly negated goal started. Currently, neither field is used.
+**
+** The MR_pneg_depth field records the depth of the pneg stack entry in
+** the interleaving of the cut stack and pneg stack entries dictated by
+** the nesting of committed choice and possibly negated contexts currently
+** active.
+*/
 
 struct MR_PNegConsumerListNodeStruct {
 	MR_Subgoal		*MR_pneg_consumer_ptr;
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.55
diff -u -b -r1.55 mercury_trace_base.c
--- runtime/mercury_trace_base.c	10 Mar 2004 04:30:39 -0000	1.55
+++ runtime/mercury_trace_base.c	12 Mar 2004 01:58:20 -0000
@@ -466,7 +466,8 @@
 }
 
 void
-MR_turn_off_debug(MR_SavedDebugState *saved_state)
+MR_turn_off_debug(MR_SavedDebugState *saved_state,
+	MR_bool include_counter_vars)
 {
 	int	i;
 
@@ -479,6 +480,11 @@
 		saved_state->MR_sds_debugflags[i] = MR_debugflag[i];
 		MR_debugflag[i] = MR_FALSE;
 	}
+
+	saved_state->MR_sds_include_counter_vars = include_counter_vars;
+	saved_state->MR_sds_trace_call_seqno = MR_trace_call_seqno;
+	saved_state->MR_sds_trace_call_depth = MR_trace_call_depth;
+	saved_state->MR_sds_trace_event_number = MR_trace_event_number;
 }
 
 void
@@ -491,6 +497,12 @@
 
 	for (i = 0; i < MR_MAXFLAG ; i++) {
 		MR_debugflag[i] = saved_state->MR_sds_debugflags[i];
+	}
+
+	if (saved_state->MR_sds_include_counter_vars) {
+		MR_trace_call_seqno = saved_state->MR_sds_trace_call_seqno;
+		MR_trace_call_depth = saved_state->MR_sds_trace_call_depth;
+		MR_trace_event_number = saved_state->MR_sds_trace_event_number;
 	}
 }
 
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.37
diff -u -b -r1.37 mercury_trace_base.h
--- runtime/mercury_trace_base.h	10 Mar 2004 04:30:39 -0000	1.37
+++ runtime/mercury_trace_base.h	12 Mar 2004 01:56:44 -0000
@@ -333,16 +333,23 @@
 ** MR_turn_off_debug saves the current values of the variables controlling 
 ** debugging (execution tracing and diagnostics) in the structure provided by
 ** the caller, and then turns them off. MR_turn_debug_back_on restores the
-** saved values from the structure.
+** saved values from the structure. If include_counter_vars is set, they also
+** save and restore the global variables containing the event and sequence
+** number counters and the call depth.
 */
 
 typedef struct {
 	MR_bool	MR_sds_trace_enabled;
 	MR_bool	MR_sds_io_tabling_enabled;
 	MR_bool	MR_sds_debugflags[MR_MAXFLAG];
+	MR_bool		MR_sds_include_counter_vars;
+	MR_Unsigned	MR_sds_trace_call_seqno;
+	MR_Unsigned	MR_sds_trace_call_depth;
+	MR_Unsigned	MR_sds_trace_event_number;
 } MR_SavedDebugState;
 
-extern	void	MR_turn_off_debug(MR_SavedDebugState *saved_state);
+extern	void	MR_turn_off_debug(MR_SavedDebugState *saved_state,
+			MR_bool include_counter_vars);
 extern	void	MR_turn_debug_back_on(MR_SavedDebugState *saved_state);
 
 /*
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/mdb_command_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.25
diff -u -b -r1.25 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	23 Oct 2003 02:02:41 -0000	1.25
+++ tests/debugger/mdb_command_test.inp	12 Mar 2004 05:12:46 -0000
@@ -51,9 +51,11 @@
 gen_stack            xyzzy xyzzy xyzzy xyzzy xyzzy
 cut_stack            xyzzy xyzzy xyzzy xyzzy xyzzy
 pneg_stack           xyzzy xyzzy xyzzy xyzzy xyzzy
+mm_stacks            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
+debug_vars           xyzzy xyzzy xyzzy xyzzy xyzzy
 proc_stats           xyzzy xyzzy xyzzy xyzzy xyzzy
 label_stats          xyzzy xyzzy xyzzy xyzzy xyzzy
 print_optionals      xyzzy xyzzy xyzzy xyzzy xyzzy
cvs diff: Diffing tests/debugger/declarative
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/mercury/mercury1/repository/tests/tabling/Mmakefile,v
retrieving revision 1.22
diff -u -b -r1.22 Mmakefile
--- tests/tabling/Mmakefile	12 Mar 2004 03:01:20 -0000	1.22
+++ tests/tabling/Mmakefile	12 Mar 2004 03:46:10 -0000
@@ -19,6 +19,9 @@
 	unused_args
 
 NONDET_PROGS = \
+	combine \
+	completed_consumer_in_solutions \
+	consumer_in_commit \
 	coup \
 	coup_det_frame \
 	coup_no_commit \
@@ -29,19 +32,20 @@
 	seq \
 	seq2 \
 	seq3 \
+	seq4 \
 	sg \
 	tc_loop \
 	tc_minimal
 
 # We don't yet pass the following minimal model tests. The reason is that
 # they contain interactions between tabling and constructs that function
-# as commited or negated contexts.
+# as committed or negated contexts.
 #
-#	consumer_in_commit
 #	consumer_in_solutions
-#	combine
+#
+# We don't yet pass the following minimal model tests for undetermined reasons.
+#
 #	coup2
-#	seq4
 
 # Tabling does not yet work in .rt grades
 ifneq "$(findstring .gc,$(GRADE))" ""
Index: tests/tabling/combine.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/combine.m,v
retrieving revision 1.1
diff -u -b -r1.1 combine.m
--- tests/tabling/combine.m	30 Oct 2002 01:42:18 -0000	1.1
+++ tests/tabling/combine.m	11 Mar 2004 06:57:07 -0000
@@ -19,16 +19,20 @@
 :- pred b(int::out) is multi.
 :- pred c(int::out) is multi.
 :- pred d(int::out) is nondet.
+:- pred e(int::out) is nondet.
 
 :- pragma minimal_model(d/1).
+:- pragma minimal_model(e/1).
 
 a(A) :-
 	d(B),
-	d(C),
+	e(C),
 	A = B * 10 + C.
 
 d(A) :-
-	b(A),
+	b(A).
+
+e(A) :-
 	c(A).
 
 b(3).
Index: tests/tabling/completed_consumer_in_solutions.exp
===================================================================
RCS file: tests/tabling/completed_consumer_in_solutions.exp
diff -N tests/tabling/completed_consumer_in_solutions.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/completed_consumer_in_solutions.exp	11 Mar 2004 07:24:43 -0000
@@ -0,0 +1,2 @@
+[1, 2, 3]
+[1, 2, 3]
Index: tests/tabling/completed_consumer_in_solutions.m
===================================================================
RCS file: tests/tabling/completed_consumer_in_solutions.m
diff -N tests/tabling/completed_consumer_in_solutions.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/completed_consumer_in_solutions.m	11 Mar 2004 07:28:11 -0000
@@ -0,0 +1,36 @@
+% This test case checks whether we get incorrect answers
+% when a consumer accesses a completed generator inside solutions.
+% The first call to solutions completes the generator for p,
+% the second call accesses the completed generator.
+
+:- module completed_consumer_in_solutions.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module int, list.
+:- import_module std_util.
+
+main --> 
+	{ q(Solns1, Solns2) },
+	io__write(Solns1),
+	io__write_string("\n"),
+	io__write(Solns2),
+	io__write_string("\n").
+
+:- pred q(list(int)::out, list(int)::out) is det.
+
+q(L1, L2) :-
+	solutions(p, L1),
+	solutions(p, L2).
+
+:- pragma minimal_model(p/1).
+:- pred p(int::out) is nondet.
+
+p(1).
+p(2).
+p(3).
Index: tests/tabling/consumer_in_commit.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/consumer_in_commit.exp,v
retrieving revision 1.1
diff -u -b -r1.1 consumer_in_commit.exp
--- tests/tabling/consumer_in_commit.exp	20 Apr 1999 11:48:37 -0000	1.1
+++ tests/tabling/consumer_in_commit.exp	11 Mar 2004 07:05:27 -0000
@@ -1,2 +1,2 @@
-Mercury runtime: Sorry, not implemented:
-committing across a suspended call to a tabled predicate
+[1, 2, 3, 4]
+[1, 2, 3, 4, 5, 6, 7, 8, 9]
Index: tests/tabling/consumer_in_commit.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/consumer_in_commit.m,v
retrieving revision 1.1
diff -u -b -r1.1 consumer_in_commit.m
--- tests/tabling/consumer_in_commit.m	20 Apr 1999 11:48:38 -0000	1.1
+++ tests/tabling/consumer_in_commit.m	11 Mar 2004 07:03:53 -0000
@@ -14,8 +14,11 @@
 :- import_module std_util.
 
 main --> 
-	{ solutions(p, Solns) },
-	io__write(Solns),
+	{ solutions(p, SolnsP) },
+	io__write(SolnsP),
+	io__write_string("\n"),
+	{ solutions(q, SolnsQ) },
+	io__write(SolnsQ),
 	io__write_string("\n").
 
 :- pred p(int).
Index: tests/tabling/seq2.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/seq2.m,v
retrieving revision 1.1
diff -u -b -r1.1 seq2.m
--- tests/tabling/seq2.m	11 Mar 2004 07:32:21 -0000	1.1
+++ tests/tabling/seq2.m	11 Mar 2004 07:43:43 -0000
@@ -20,20 +20,25 @@
 	io__write(Solns),
 	io__write_string("\n").
 
-:- pred p(int).
-:- mode p(out) is nondet.
+:- pred p(int::out) is nondet.
 
 :- pragma minimal_model(p/1).
 
 p(X) :-
 	(
 		p(Y),
-		0 =< Y, Y < 10,
-		X is -Y - 1
+		between(0, Y, 9),
+		X = -Y - 1
 	;
 		p(Y),
-		-10 < Y, Y =< 10,
-		X is -Y + 1
+		between(-9, Y, 0),
+		X = -Y + 1
 	;
 		X = 0
 	).
+
+:- pred between(int::in, int::in, int::in) is semidet.
+
+between(A, B, C) :-
+	A =< B,
+	B =< C.
Index: tests/tabling/seq4.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/seq4.exp,v
retrieving revision 1.1
diff -u -b -r1.1 seq4.exp
--- tests/tabling/seq4.exp	12 Mar 2004 03:01:21 -0000	1.1
+++ tests/tabling/seq4.exp	12 Mar 2004 03:46:21 -0000
@@ -1,2 +1,2 @@
 P = [1, 2, 3, 4, 6, 8, 9, 12, 16, 18]
-Q = [1, 2, 4, 6, 8, 12, 16, 16]
+Q = [1, 2, 4, 8, 16]
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/mercury/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.66
diff -u -b -r1.66 mercury_trace.c
--- trace/mercury_trace.c	10 Mar 2004 01:08:38 -0000	1.66
+++ trace/mercury_trace.c	11 Mar 2004 03:46:29 -0000
@@ -148,6 +148,12 @@
         depth = (MR_Unsigned) MR_call_depth_framevar(MR_curfr);
     }
 
+#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_TABLE_DEBUG)
+    if ((MR_Trace_Port) layout->MR_sll_port == MR_PORT_CALL) {
+        MR_subgoal_debug_cur_proc = layout->MR_sll_entry;
+    }
+#endif
+
     if (layout->MR_sll_hidden && !MR_trace_unhide_events) {
         return NULL;
     }
@@ -441,12 +447,6 @@
     MR_compute_max_mr_num(event_info.MR_max_mr_num, layout);
     /* 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) {
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.72
diff -u -b -r1.72 mercury_trace_external.c
--- trace/mercury_trace_external.c	26 Jan 2004 21:09:47 -0000	1.72
+++ trace/mercury_trace_external.c	11 Mar 2004 15:55:30 -0000
@@ -670,7 +670,7 @@
 				** MR_dump_nondet_stack() (as we do
 				** with MR_dump_stack_record_print()).
 				*/						
-				MR_dump_nondet_stack(stdout, 0,
+				MR_dump_nondet_stack(stdout, NULL, 0,
 					MR_saved_maxfr(saved_regs));
 				MR_send_message_to_socket("ok");
 				break;
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.168
diff -u -b -r1.168 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	10 Mar 2004 04:31:06 -0000	1.168
+++ trace/mercury_trace_internal.c	12 Mar 2004 01:57:16 -0000
@@ -439,9 +439,11 @@
 static	MR_TraceCmdFunc	MR_trace_cmd_gen_stack;
 static	MR_TraceCmdFunc	MR_trace_cmd_cut_stack;
 static	MR_TraceCmdFunc	MR_trace_cmd_pneg_stack;
+static	MR_TraceCmdFunc	MR_trace_cmd_mm_stacks;
 static	MR_TraceCmdFunc	MR_trace_cmd_nondet_stack;
 static	MR_TraceCmdFunc	MR_trace_cmd_stack_regs;
 static	MR_TraceCmdFunc	MR_trace_cmd_all_regs;
+static	MR_TraceCmdFunc	MR_trace_cmd_debug_vars;
 static	MR_TraceCmdFunc	MR_trace_cmd_table_io;
 static	MR_TraceCmdFunc	MR_trace_cmd_proc_stats;
 static	MR_TraceCmdFunc	MR_trace_cmd_label_stats;
@@ -659,7 +661,7 @@
 	** do any I/O tabling.
 	*/
 
-	MR_turn_off_debug(&MR_saved_debug_state);
+	MR_turn_off_debug(&MR_saved_debug_state, MR_FALSE);
 
 	MR_trace_internal_ensure_init();
 
@@ -674,9 +676,9 @@
 	** to allow them to be modified by MR_trace_retry().
 	*/
 
+	event_details.MR_event_number = MR_trace_event_number;
 	event_details.MR_call_seqno = MR_trace_call_seqno;
 	event_details.MR_call_depth = MR_trace_call_depth;
-	event_details.MR_event_number = MR_trace_event_number;
 
 	MR_trace_init_point_vars(event_info->MR_event_sll,
 		event_info->MR_saved_regs, event_info->MR_trace_port,
@@ -3463,6 +3465,39 @@
 }
 
 static MR_Next
+MR_trace_cmd_mm_stacks(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_gen_stack(MR_mdb_out);
+		fprintf(MR_mdb_out, "\n");
+		MR_print_cut_stack(MR_mdb_out);
+		fprintf(MR_mdb_out, "\n");
+		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)
@@ -3503,12 +3538,12 @@
 		int	saved_level;
 
 		saved_level = MR_trace_current_level();
-		MR_dump_nondet_stack_from_layout(MR_mdb_out, limit,
+		MR_dump_nondet_stack_from_layout(MR_mdb_out, NULL, limit,
 			MR_saved_maxfr(saved_regs), layout,
 			MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
 		MR_trace_set_level(saved_level, MR_print_optionals);
 	} else {
-		MR_dump_nondet_stack(MR_mdb_out, limit,
+		MR_dump_nondet_stack(MR_mdb_out, NULL, limit,
 			MR_saved_maxfr(saved_regs));
 	}
 }
@@ -3557,6 +3592,20 @@
 }
 
 static MR_Next
+MR_trace_cmd_debug_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+	if (word_count == 1) {
+		MR_print_debug_vars(MR_mdb_out, event_details);
+	} else {
+		MR_trace_usage("developer", "debug_vars");
+	}
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Next
 MR_trace_cmd_table_io(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
@@ -6927,11 +6976,15 @@
 		NULL, MR_trace_null_completer },
 	{ "developer", "pneg_stack", MR_trace_cmd_pneg_stack,
 		NULL, MR_trace_null_completer },
+	{ "developer", "mm_stacks", MR_trace_cmd_mm_stacks,
+		NULL, MR_trace_null_completer },
 	{ "developer", "nondet_stack", MR_trace_cmd_nondet_stack,
 		MR_trace_stack_cmd_args, MR_trace_null_completer },
 	{ "developer", "stack_regs", MR_trace_cmd_stack_regs,
 		NULL, MR_trace_null_completer },
 	{ "developer", "all_regs", MR_trace_cmd_all_regs,
+		NULL, MR_trace_null_completer },
+	{ "developer", "debug_vars", MR_trace_cmd_debug_vars,
 		NULL, MR_trace_null_completer },
 	{ "developer", "proc_stats", MR_trace_cmd_proc_stats,
 		NULL, MR_trace_filename_completer },
Index: trace/mercury_trace_util.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.c,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_trace_util.c
--- trace/mercury_trace_util.c	21 Nov 2002 08:00:58 -0000	1.10
+++ trace/mercury_trace_util.c	11 Mar 2004 04:59:46 -0000
@@ -149,3 +149,20 @@
 		(long) MR_saved_reg(saved_regs, 5));
 #endif
 }
+
+void
+MR_print_debug_vars(FILE *fp, MR_Event_Details *event_details)
+{
+#ifndef MR_HIGHLEVEL_CODE
+	fprintf(fp, "from event details:\n");
+	fprintf(fp, "call event %d, call seq %d, depth %d\n",
+		event_details->MR_event_number,
+		event_details->MR_call_seqno,
+		event_details->MR_call_depth);
+	fprintf(fp, "from global vars:\n");
+	fprintf(fp, "call event %d, call seq %d, depth %d\n",
+		MR_trace_event_number,
+		MR_trace_call_seqno,
+		MR_trace_call_depth);
+#endif
+}
Index: trace/mercury_trace_util.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.h,v
retrieving revision 1.9
diff -u -b -r1.9 mercury_trace_util.h
--- trace/mercury_trace_util.h	15 Nov 2002 04:50:49 -0000	1.9
+++ trace/mercury_trace_util.h	11 Mar 2004 04:56:56 -0000
@@ -20,6 +20,7 @@
 #include "mercury_types.h"		/* for MR_Word etc */
 #include "mercury_library_types.h"	/* for MercuryFile */
 #include <stdio.h>			/* for FILE        */
+#include "mercury_trace.h"		/* for MR_Event_Details */
 
 /*
 ** When using the heap pointer, we need to restore it, in case it is
@@ -90,5 +91,6 @@
 extern	void	MR_print_tabling_regs(FILE *fp, MR_Word *saved_regs);
 extern	void	MR_print_succip_reg(FILE *fp, MR_Word *saved_regs);
 extern	void	MR_print_r_regs(FILE *fp, MR_Word *saved_regs);
+extern	void	MR_print_debug_vars(FILE *fp, MR_Event_Details *event_details);
 
 #endif /* MERCURY_TRACE_UTIL_H */
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