[m-rev.] for review: atoms in the debugger

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Jan 11 20:09:49 AEDT 2002


Here is an updated log message and diff, followed by a relative diff.

Zoltan.

Estimated hours taken: 20
Branches: main

Give the debugger the ability to print goals.

NEWS:
	Mention the new ability.

browser/browser_info.m:
	Define a new type, browser_term, which represents either a plain term,
	or a "synthetic term", which is a string (predicate or function name),
	a list of argument values, and an indication of whether the synthetic
	term is a predicate goal (i.e. of the form p(a1, ..., an)) or a
	function goal (i.e. of the form f(a1, ..., an-1) = an).

	Add utility predicates for processing browser_terms.

browser/browse.m:
	Add predicates for printing and browsing synthetic terms, and export
	them to C code.

browser/browse.m:
browser/size_pretty.m:
	Generalize lots of predicates to handle browser_terms, not just plain
	terms.

browser/util.m:
	Add a new type, "unbound", for use by mercury_trace_vars.c.

library/pprint.m:
	Add functions for converting synthetic terms to docs.

	Fix a potential efficiency problem: an unnecessary deconstruct.

runtime/mercury_type_info.h:
	Add macros for defining static type_infos in C code.

	Add macros for computing the names of type_ctor_infos even in non-hlc
	grades.

	Give C code access to the representation of bools and of values of
	the new type "unbound".

trace/mercury_trace_browse.[ch]:
	Add functions for printing goals.

trace/mercury_trace_internal.c:
	Add code to recognize and handle the commands "print goal" and
	"browse goal".

doc/user_guide.texi:
	Document the new commands.

trace/mercury_trace_vars.[ch]:
	Add a function to compute the components of synthetic terms.

tests/debugger/browse_pretty.{inp,exp,exp2}:
	Add new commands to the input to test the printing and browsing of
	predicate goals, and update the expected outputs accordingly.

tests/debugger/polymorphic_output.{inp,exp,exp2}:
	Add new commands to the input to test the printing and browsing of
	function goals, and update the expected outputs accordingly.

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

the updated diff:

Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.235
diff -u -b -r1.235 NEWS
--- NEWS	2002/01/09 06:41:26	1.235
+++ NEWS	2002/01/09 06:56:58
@@ -156,6 +156,10 @@
 
 Changes to the Mercury implementation:
 
+* The debugger can now print goals just as Prolog debuggers do. At an exit
+  port of e.g. append, the command "print goal" will print the current goal
+  in a form such as "append([1], [2], [1, 2])".
+
 * You can now navigate terms in the debugger by argument name as well as by
   argument number.
 
Index: browser/browse.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/browse.m,v
retrieving revision 1.23
diff -u -b -r1.23 browse.m
--- browser/browse.m	2001/12/19 06:50:18	1.23
+++ browser/browse.m	2002/01/09 05:51:30
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 1998-2001 The University of Melbourne.
+% Copyright (C) 1998-2002 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,8 +20,8 @@
 
 :- interface.
 
-:- import_module io, std_util, list.
 :- import_module mdb__browser_info.
+:- import_module io, bool, std_util, list.
 
 	% The interactive term browser.  The caller type will be `browse', and
 	% the default format for the `browse' caller type will be used.
@@ -38,6 +38,22 @@
 			browser_persistent_state, io__state, io__state).
 :- mode browse__browse_format(in, in, in, in, in, out, di, uo) is det.
 
+	% A version of browse__browse that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
+:- pred browse__browse_synthetic(string::in, list(univ)::in, bool::in,
+	io__input_stream::in, io__output_stream::in, maybe(list(dir))::out,
+	browser_persistent_state::in, browser_persistent_state::out,
+	io__state::di, io__state::uo) is det.
+
+	% A version of browse__browse_format that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
+:- pred browse__browse_format_synthetic(string::in, list(univ)::in, bool::in,
+	io__input_stream::in, io__output_stream::in, portray_format::in,
+	browser_persistent_state::in, browser_persistent_state::out,
+	io__state::di, io__state::uo) is det.
+
 	% The browser interface for the external debugger.  The caller type
 	% will be `browse', and the default format will be used.
 	%
@@ -50,16 +66,28 @@
 	% `print' or `print_all'.  The default portray format for that
 	% caller type is used.
 	%
-:- pred browse__print(T, io__output_stream, browse_caller_type,
-			browser_persistent_state, io__state, io__state).
-:- mode browse__print(in, in, in, in, di, uo) is det.
+:- pred browse__print(T::in, io__output_stream::in, browse_caller_type::in,
+	browser_persistent_state::in, io__state::di, io__state::uo) is det.
+
+	% A version of browse__print that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
+:- pred browse__print_synthetic(string::in, list(univ)::in, bool::in,
+	io__output_stream::in, browse_caller_type::in,
+	browser_persistent_state::in, io__state::di, io__state::uo) is det.
 
 	% As above, except that the supplied format will override the default.
 	%
-:- pred browse__print_format(T, io__output_stream, browse_caller_type,
-			portray_format, browser_persistent_state,
-			io__state, io__state).
-:- mode browse__print_format(in, in, in, in, in, di, uo) is det.
+:- pred browse__print_format(T::in, io__output_stream::in,
+	browse_caller_type::in, portray_format::in,
+	browser_persistent_state::in, io__state::di, io__state::uo) is det.
+
+	% A version of browse__print_format that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
+:- pred browse__print_format_synthetic(string::in, list(univ)::in, bool::in,
+	io__output_stream::in, browse_caller_type::in, portray_format::in,
+	browser_persistent_state::in, io__state::di, io__state::uo) is det.
 
 	% Estimate the total term size, in characters,
 	% We count the number of characters in the functor,
@@ -79,12 +107,14 @@
 	% by definition the caller is not interested in the accurate value.
 :- pred term_size_left_from_max(univ::in, int::in, int::out) is det.
 
+:- pred browser_term_size_left_from_max(browser_term::in,
+	int::in, int::out) is det.
+
 %---------------------------------------------------------------------------%
 :- implementation.
 
 :- import_module mdb__parse, mdb__util, mdb__frame, mdb__sized_pretty.
 :- import_module string, parser, require, std_util, int, char, pprint.
-:- import_module bool.
 
 %---------------------------------------------------------------------------%
 %
@@ -96,12 +126,20 @@
 	"ML_BROWSE_browse").
 :- pragma export(browse__browse_format(in, in, in, in, in, out, di, uo),
 	"ML_BROWSE_browse_format").
+:- pragma export(browse__browse_synthetic(in, in, in, in, in, out,
+	in, out, di, uo), "ML_BROWSE_browse_synthetic").
+:- pragma export(browse__browse_format_synthetic(in, in, in, in, in, in,
+	in, out, di, uo), "ML_BROWSE_browse_format_synthetic").
 :- pragma export(browse__browse_external(in, in, in, in, out, di, uo),
 	"ML_BROWSE_browse_external").
 :- pragma export(browse__print(in, in, in, in, di, uo),
 	"ML_BROWSE_print").
 :- pragma export(browse__print_format(in, in, in, in, in, di, uo),
 	"ML_BROWSE_print_format").
+:- pragma export(browse__print_synthetic(in, in, in, in, in, in, di, uo),
+	"ML_BROWSE_print_synthetic").
+:- pragma export(browse__print_format_synthetic(in, in, in, in, in, in, in,
+	di, uo), "ML_BROWSE_print_format_synthetic").
 
 %---------------------------------------------------------------------------%
 % If the term browser is called from the internal debugger, input is
@@ -129,31 +167,46 @@
 %
 
 browse__print(Term, OutputStream, Caller, State) -->
-	browse__print_common(Term, OutputStream, Caller, no, State).
+	browse__print_common(plain_term(univ(Term)), OutputStream,
+		Caller, no, State).
 
 browse__print_format(Term, OutputStream, Caller, Format, State) -->
-	browse__print_common(Term, OutputStream, Caller, yes(Format), State).
+	browse__print_common(plain_term(univ(Term)), OutputStream,
+		Caller, yes(Format), State).
 
-:- pred browse__print_common(T, io__output_stream, browse_caller_type,
-		maybe(portray_format), browser_persistent_state,
-		io__state, io__state).
-:- mode browse__print_common(in, in, in, in, in, di, uo) is det.
+browse__print_synthetic(FunctorString, Args, IsFunc, OutputStream,
+		Caller, State) -->
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse__print_common(BrowserTerm, OutputStream, Caller, no, State).
+
+browse__print_format_synthetic(FunctorString, Args, IsFunc, OutputStream,
+		Caller, Format, State) -->
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse__print_common(BrowserTerm, OutputStream,
+		Caller, yes(Format), State).
+
+:- pred browse__print_common(browser_term::in, io__output_stream::in,
+	browse_caller_type::in, maybe(portray_format)::in,
+	browser_persistent_state::in, io__state::di, io__state::uo) is det.
 
-browse__print_common(Term, OutputStream, Caller, MaybeFormat, State) -->
-	{ browser_info__init(Term, MaybeFormat, State, Info) },
+browse__print_common(BrowserTerm, OutputStream, Caller, MaybeFormat, State) -->
+	{ Info = browser_info__init(BrowserTerm, MaybeFormat, State) },
 	io__set_output_stream(OutputStream, OldStream),
 	{ browser_info__get_format(Info, Caller, MaybeFormat, Format) },
 	%
-	% We assume that the variable name has been printed on the
-	% first part of the line.  If the format is something other than
+	% For plain terms, we assume that the variable name has been printed
+	% on the first part of the line.  If the format is something other than
 	% `flat', then we need to start on the next line.
 	%
 	(
-		{ Format = flat }
+		{ BrowserTerm = plain_term(_) },
+		{ Format \= flat }
 	->
-		[]
-	;
 		io__nl
+	;
+		[]
 	),
 	portray(internal, Caller, no, Info),
 	io__set_output_stream(OldStream, _).
@@ -164,29 +217,40 @@
 %
 
 browse__browse(Object, InputStream, OutputStream, MaybeMark, State0, State) -->
-	browse_common(internal, Object, InputStream, OutputStream, 
-		no, MaybeMark, State0, State).
+	browse_common(internal, plain_term(univ(Object)),
+		InputStream, OutputStream, no, MaybeMark, State0, State).
 
 browse__browse_format(Object, InputStream, OutputStream, Format,
 		State0, State) -->
+	browse_common(internal, plain_term(univ(Object)),
+		InputStream, OutputStream, yes(Format), _, State0, State).
 
-	browse_common(internal, Object, InputStream, OutputStream,
-		yes(Format), _, State0, State).
+browse__browse_synthetic(FunctorString, Args, IsFunc,
+		InputStream, OutputStream, MaybeMark, State0, State) -->
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse_common(internal, BrowserTerm,
+		InputStream, OutputStream, no, MaybeMark, State0, State).
+
+browse__browse_format_synthetic(FunctorString, Args, IsFunc,
+		InputStream, OutputStream, Format, State0, State) -->
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse_common(internal, BrowserTerm,
+		InputStream, OutputStream, yes(Format), _, State0, State).
 
 browse__browse_external(Object, InputStream, OutputStream, State0, State) -->
-	browse_common(external, Object, InputStream, OutputStream, 
-		no, _, State0, State).
+	browse_common(external, plain_term(univ(Object)),
+		InputStream, OutputStream, no, _, State0, State).
 
-:- pred browse_common(debugger::in, T::in, io__input_stream::in,
+:- pred browse_common(debugger::in, browser_term::in, io__input_stream::in,
 		io__output_stream::in, maybe(portray_format)::in,
 		maybe(list(dir))::out, browser_persistent_state::in,
-		browser_persistent_state::out, io__state::di, io__state::uo)
-		is det.
+	browser_persistent_state::out, io__state::di, io__state::uo) is det.
 
 browse_common(Debugger, Object, InputStream, OutputStream, MaybeFormat,
 		MaybeMark, State0, State) -->
-	
-	{ browser_info__init(Object, MaybeFormat, State0, Info0) },
+	{ Info0 = browser_info__init(Object, MaybeFormat, State0) },
 	io__set_input_stream(InputStream, OldInputStream),
 	io__set_output_stream(OutputStream, OldOutputStream),
 	% startup_message,
@@ -196,6 +260,29 @@
 	{ MaybeMark = Info ^ maybe_mark },
 	{ State = Info ^ state }.
 
+% This predicate converts synthetic terms from the representation used in the
+% trace directory (as a list of arguments, the last of which represents the
+% return value for function calls) to the representation used in the browser
+% directory, in which a function call's return value is stored separately from
+% the other arguments.
+%
+% The reason why the trace directory does not use the latter representation
+% is that it would require C code to construct values of type maybe(T).
+
+:- pred synthetic_term_to_browser_term(string::in, list(univ)::in, bool::in,
+	browser_term::out) is det.
+
+synthetic_term_to_browser_term(FunctorString, Args, IsFunc, BrowserTerm) :-
+	(
+		IsFunc = no,
+		BrowserTerm = synthetic_term(FunctorString, Args, no)
+	;
+		IsFunc = yes,
+		list__split_last_det(Args, FuncArgs, Return),
+		BrowserTerm = synthetic_term(FunctorString, FuncArgs,
+			yes(Return))
+	).
+
 :- pred browse_main_loop(debugger, browser_info, browser_info, 
 		io__state, io__state).
 :- mode browse_main_loop(in, in, out, di, uo) is det.
@@ -233,7 +320,6 @@
 :- pred prompt(string::out) is det.
 prompt("browser> ").
 
-
 :- pred run_command(debugger::in, command::in, bool::out, browser_info::in,
 		browser_info::out, io__state::di, io__state::uo) is det.
 
@@ -403,10 +489,10 @@
 	{ set_path(Path, Info0, Info) },
 	portray(Debugger, Caller, MaybeFormat, Info).
 
-:- pred portray_flat(debugger, univ, format_params, io__state, io__state).
-:- mode portray_flat(in, in, in, di, uo) is det.
+:- pred portray_flat(debugger::in, browser_term::in, format_params::in,
+	io__state::di, io__state::uo) is det.
 
-portray_flat(Debugger, Univ, Params) -->
+portray_flat(Debugger, BrowserTerm, Params) -->
 	%
 	% io__write handles the special cases such as lists,
 	% operators, etc. better, so we prefer to use it if we
@@ -417,44 +503,67 @@
 	%
 	% XXX this ignores the maximum number of lines
 	%
-	{ max_print_size(MaxSize) },
-	{ term_size_left_from_max(Univ, MaxSize, RemainingSize) },
+	{ browser_term_size_left_from_max(BrowserTerm, max_print_size,
+		RemainingSize) },
 	( { RemainingSize >= 0 } ->
-		io__write_univ(Univ)
+		portray_flat_write_browser_term(BrowserTerm)
 	;
-		{ term_to_string(Univ, Params ^ size, Params ^ depth, Str) },
+		{ browser_term_to_string(BrowserTerm, Params ^ size,
+			Params ^ depth, Str) },
 		write_string_debugger(Debugger, Str)
 	).
 
-:- pred portray_verbose(debugger, univ, format_params, io__state, io__state).
-:- mode portray_verbose(in, in, in, di, uo) is det.
+:- pred portray_flat_write_browser_term(browser_term::in,
+	io__state::di, io__state::uo) is det.
 
-portray_verbose(Debugger, Univ, Params) -->
-	{ term_to_string_verbose(Univ, Params ^ size, Params ^ depth,
-			Params ^ width, Params ^ lines, Str) },
+portray_flat_write_browser_term(plain_term(Univ)) -->
+	io__write_univ(Univ).
+portray_flat_write_browser_term(synthetic_term(Functor, Args, MaybeReturn)) -->
+	io__write_string(Functor),
+	( { Args = [] } ->
+		[]
+	;
+		io__write_string("("),
+		io__write_list(Args, ", ", io__write_univ),
+		io__write_string(")")
+	),
+	(
+		{ MaybeReturn = yes(Return) },
+		io__write_string(" = "),
+		io__write_univ(Return)
+	;
+		{ MaybeReturn = no }
+	).
+
+:- pred portray_verbose(debugger::in, browser_term::in, format_params::in,
+	io__state::di, io__state::uo) is det.
+
+portray_verbose(Debugger, BrowserTerm, Params) -->
+	{ browser_term_to_string_verbose(BrowserTerm, Params ^ size,
+		Params ^ depth, Params ^ width, Params ^ lines, Str) },
 	write_string_debugger(Debugger, Str).
 
-:- pred portray_raw_pretty(debugger, univ, format_params, io__state, io__state).
-:- mode portray_raw_pretty(in, in, in, di, uo) is det.
+:- pred portray_raw_pretty(debugger::in, browser_term::in, format_params::in,
+	io__state::di, io__state::uo) is det.
 
-portray_raw_pretty(Debugger, Univ, Params) -->
-	{ term_to_string_raw_pretty(Univ, Params ^ width, 
+portray_raw_pretty(Debugger, BrowserTerm, Params) -->
+	{ browser_term_to_string_raw_pretty(BrowserTerm, Params ^ width, 
 			Params ^ depth, Str) },
 	write_string_debugger(Debugger, Str).
 
+:- pred portray_pretty(debugger::in, browser_term::in, format_params::in,
+	io__state::di, io__state::uo) is det.
 
-:- pred portray_pretty(debugger, univ, format_params, io__state, io__state).
-:- mode portray_pretty(in, in, in, di, uo) is det.
-
-portray_pretty(Debugger, Univ, Params) -->
-	{ sized_pretty__univ_to_string_line(Univ, Params ^ width, 
-			Params ^ lines, Str) },
+portray_pretty(Debugger, BrowserTerm, Params) -->
+	{ sized_pretty__browser_term_to_string_line(BrowserTerm,
+		Params ^ width, Params ^ lines, Str) },
 	write_string_debugger(Debugger, Str).
 
 	% The maximum estimated size for which we use `io__write'.
-:- pred max_print_size(int::out) is det.
-max_print_size(60).
+:- func max_print_size = int.
 
+max_print_size = 60.
+
 term_size_left_from_max(Univ, MaxSize, RemainingSize) :-
 	(
 		MaxSize < 0
@@ -465,6 +574,7 @@
 			Functor, Arity, Args)
 	->
 		string__length(Functor, FunctorSize),
+		% "()", plus Arity-1 times ", "
 		PrincipalSize = FunctorSize + Arity * 2,
 		MaxArgsSize = MaxSize - PrincipalSize,
 		list__foldl(term_size_left_from_max,
@@ -473,71 +583,106 @@
 		RemainingSize = -1
 	).
 
+browser_term_size_left_from_max(BrowserTerm, MaxSize, RemainingSize) :-
+	(
+		BrowserTerm = plain_term(Univ),
+		term_size_left_from_max(Univ, MaxSize, RemainingSize)
+	;
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		string__length(Functor, FunctorSize),
+		list__length(Args, Arity),
+		(
+			MaybeReturn = yes(_),
+			% "()", " = ", plus Arity-1 times ", "
+			PrincipalSize = FunctorSize + Arity * 2 + 3
+		;
+			MaybeReturn = no,
+			% "()", plus Arity-1 times ", "
+			PrincipalSize = FunctorSize + Arity * 2
+		),
+		MaxArgsSize = MaxSize - PrincipalSize,
+		list__foldl(term_size_left_from_max,
+			Args, MaxArgsSize, RemainingSize)
+	).
+
 %---------------------------------------------------------------------------%
 %
 % Single-line representation of a term.
 %
+
+:- pred browser_term_to_string(browser_term::in, int::in, int::in,
+	string::out) is det.
 
-:- pred term_to_string(univ, int, int, string).
-:- mode term_to_string(in, in, in, out) is det.
-term_to_string(Univ, MaxSize, MaxDepth, Str) :-
+browser_term_to_string(BrowserTerm, MaxSize, MaxDepth, Str) :-
 	CurSize = 0,
 	CurDepth = 0,
-	term_to_string_2(Univ, MaxSize, CurSize, _NewSize,
+	browser_term_to_string_2(BrowserTerm, MaxSize, CurSize, _NewSize,
 		MaxDepth, CurDepth, Str).
 
 	% Note: When the size limit is reached, we simply display
-	% further subterms compressed. We don't just stopping printing.
+	% further subterms compressed. We don't just stop printing.
 	% XXX: Is this reasonable?
-:- pred term_to_string_2(univ, int, int, int, int, int, string).
-:- mode term_to_string_2(in, in, in, out, in, in, out) is det.
-term_to_string_2(Univ, MaxSize, CurSize, NewSize, MaxDepth, CurDepth, Str) :-
+:- pred browser_term_to_string_2(browser_term::in, int::in, int::in, int::out,
+	int::in, int::in, string::out) is det.
+
+browser_term_to_string_2(BrowserTerm, MaxSize, CurSize, NewSize,
+		MaxDepth, CurDepth, Str) :-
 	(
 		CurSize < MaxSize,
 		CurDepth < MaxDepth,
-		limited_deconstruct(univ_value(Univ), MaxSize, Functor,
-			_Arity, Args)
+		limited_deconstruct_browser_term(BrowserTerm, MaxSize, Functor,
+			_Arity, Args, MaybeReturn)
 	->
-		CurSize1 is CurSize + 1,
-		CurDepth1 is CurDepth + 1,
-		term_to_string_list(Args, MaxSize, CurSize1, NewSize,
+		CurSize1 = CurSize + 1,
+		CurDepth1 = CurDepth + 1,
+		args_to_string_list(Args, MaxSize, CurSize1, NewSize1,
 			MaxDepth, CurDepth1, ArgStrs),
-		brack_args(ArgStrs, BrackArgsStr),
-		string__append_list([Functor, BrackArgsStr], Str)
+		BracketedArgsStr = bracket_string_list(ArgStrs),
+		(
+			MaybeReturn = yes(Return),
+			browser_term_to_string_2(plain_term(Return), MaxSize,
+				NewSize1, NewSize, MaxDepth, CurDepth1,
+				ReturnStr),
+			string__append_list([Functor, BracketedArgsStr,
+				" = ", ReturnStr], Str)
+		;
+			MaybeReturn = no,
+			NewSize = NewSize1,
+			string__append_list([Functor, BracketedArgsStr], Str)
+		)
 	;
 		% Str = "...",
-		term_compress(Univ, Str),
+		browser_term_compress(BrowserTerm, Str),
 		NewSize = CurSize
 	).
 
-:- pred term_to_string_list(list(univ), int, int, int, int, int, list(string)).
-:- mode term_to_string_list(in, in, in, out, in, in, out) is det.
-term_to_string_list([], _MaxSize, CurSize, NewSize,
+:- pred args_to_string_list(list(univ)::in, int::in, int::in, int::out,
+	int::in, int::in, list(string)::out) is det.
+
+args_to_string_list([], _MaxSize, CurSize, NewSize,
 		_MaxDepth, _CurDepth, Strs) :-
 	Strs = [],
 	NewSize = CurSize.
-term_to_string_list([Univ | Univs], MaxSize, CurSize, NewSize,
+args_to_string_list([Univ | Univs], MaxSize, CurSize, NewSize,
 		MaxDepth, CurDepth, Strs) :-
-	term_to_string_2(Univ, MaxSize, CurSize, NewSize1,
+	browser_term_to_string_2(plain_term(Univ), MaxSize, CurSize, NewSize1,
 		MaxDepth, CurDepth, Str),
-	term_to_string_list(Univs, MaxSize, NewSize1, NewSize,
+	args_to_string_list(Univs, MaxSize, NewSize1, NewSize,
 		MaxDepth, CurDepth, RestStrs),
 	Strs = [Str | RestStrs].
 
+:- func bracket_string_list(list(string)) = string.
 
-:- pred brack_args(list(string), string).
-:- mode brack_args(in, out) is det.
-brack_args(Args, Str) :-
+bracket_string_list(Args) = Str :-
 	( Args = [] ->
 		Str = ""
 	;
-		comma_args(Args, CommaStr),
-		string__append_list(["(", CommaStr, ")"], Str)
+		string__append_list(["(", comma_string_list(Args), ")"], Str)
 	).
+
+:- func comma_string_list(list(string)) = string.
 
-:- pred comma_args(list(string), string).
-:- mode comma_args(in, out) is det.
-comma_args(Args, Str) :-
+comma_string_list(Args) = Str :-
 	(
 		Args = [],
 		Str = ""
@@ -546,19 +691,25 @@
 		Str = S
 	;
 		Args = [S1, S2 | Ss],
-		comma_args([S2 | Ss], Rest),
+		Rest = comma_string_list([S2 | Ss]),
 		string__append_list([S1, ", ", Rest], Str)
 	).
 
-:- pred term_compress(univ, string).
-:- mode term_compress(in, out) is det.
-term_compress(Univ, Str) :-
-	functor(univ_value(Univ), Functor, Arity),
+:- pred browser_term_compress(browser_term::in, string::out) is det.
+
+browser_term_compress(BrowserTerm, Str) :-
+	functor_browser_term(BrowserTerm, Functor, Arity, IsFunc),
 	( Arity = 0 ->
 		Str = Functor
 	;
-		int_to_string(Arity, ArityS),
-		append_list([Functor, "/", ArityS], Str)
+		int_to_string(Arity, ArityStr),
+		(
+			IsFunc = yes,
+			append_list([Functor, "/", ArityStr, "+1"], Str)
+		;
+			IsFunc = no,
+			append_list([Functor, "/", ArityStr], Str)
+		)
 	).
 	
 %---------------------------------------------------------------------------%
@@ -568,13 +719,17 @@
 % provides no way of doing this.
 %
 
-:- pred term_to_string_raw_pretty(univ, int, int, string).
-:- mode term_to_string_raw_pretty(in, in, in, out) is det.
+:- pred browser_term_to_string_raw_pretty(browser_term::in, int::in, int::in,
+	string::out) is det.
 
-term_to_string_raw_pretty(Univ, Width, MaxDepth, Str) :-
+browser_term_to_string_raw_pretty(plain_term(Univ), Width, MaxDepth, Str) :-
 	Value = univ_value(Univ),
 	Doc = to_doc(MaxDepth, Value),
 	Str = to_string(Width, Doc).
+browser_term_to_string_raw_pretty(synthetic_term(Functor, Args, MaybeReturn),
+		Width, MaxDepth, Str) :-
+	Doc = synthetic_term_to_doc(MaxDepth, Functor, Args, MaybeReturn),
+	Str = to_string(Width, Doc).
 
 %---------------------------------------------------------------------------%
 %
@@ -582,62 +737,68 @@
 % Numbering makes it easier to change to subterms.
 %
 
-:- pred term_to_string_verbose(univ, int, int, int, int, string).
-:- mode term_to_string_verbose(in, in, in, in, in, out) is det.
-term_to_string_verbose(Univ, MaxSize, MaxDepth, X, Y, Str) :-
+:- pred browser_term_to_string_verbose(browser_term::in, int::in, int::in,
+	int::in, int::in, string::out) is det.
+
+browser_term_to_string_verbose(BrowserTerm, MaxSize, MaxDepth, X, Y, Str) :-
 	CurSize = 0,
 	CurDepth = 0,
-	term_to_string_verbose_2(Univ, MaxSize, CurSize, _NewSize,
-		MaxDepth, CurDepth, Frame),
+	browser_term_to_string_verbose_2(BrowserTerm, MaxSize, CurSize,
+		_NewSize, MaxDepth, CurDepth, Frame),
 	frame__clip(X-Y, Frame, ClippedFrame),
 	unlines(ClippedFrame, Str).
+
+:- pred browser_term_to_string_verbose_2(browser_term::in, int::in, int::in,
+	int::out, int::in, int::in, frame::out) is det.
 
-:- pred term_to_string_verbose_2(univ, int, int, int, int, int, frame).
-:- mode term_to_string_verbose_2(in, in, in, out, in, in, out) is det.
-term_to_string_verbose_2(Univ, MaxSize, CurSize, NewSize,
+browser_term_to_string_verbose_2(BrowserTerm, MaxSize, CurSize, NewSize,
 		MaxDepth, CurDepth, Frame) :-
 	(
 		CurSize < MaxSize,
 		CurDepth < MaxDepth,
-		limited_deconstruct(univ_value(Univ), MaxSize, Functor,
-			_Arity, Args)
+		limited_deconstruct_browser_term(BrowserTerm, MaxSize, Functor,
+			_Arity, Args0, MaybeReturn)
 	->
+		% XXX we should consider formatting function terms differently.
+		(
+			MaybeReturn = yes(Return),
+			list__append(Args0, [Return], Args)
+		;
+			MaybeReturn = no,
+			Args = Args0
+		),
 		CurSize1 is CurSize + 1,
 		CurDepth1 is CurDepth + 1,
 		ArgNum = 1,
-		term_to_string_verbose_list(Args, ArgNum,
-			MaxSize, CurSize1, NewSize,
-			MaxDepth, CurDepth1, ArgsFrame),
+		args_to_string_verbose_list(Args, ArgNum, MaxSize, CurSize1,
+			NewSize, MaxDepth, CurDepth1, ArgsFrame),
 		frame__vglue([Functor], ArgsFrame, Frame)
 	;
-		term_compress(Univ, Line),
+		browser_term_compress(BrowserTerm, Line),
 		Frame = [Line],
 		NewSize = CurSize
 	).
 
-:- pred term_to_string_verbose_list(list(univ), int, int, int, int,
-	int, int, frame).
-:- mode term_to_string_verbose_list(in, in, in, in, out, in, in, out) is det.
+:- pred args_to_string_verbose_list(list(univ)::in, int::in, int::in,
+	int::in, int::out, int::in, int::in, frame::out) is det.
 
-term_to_string_verbose_list([], _ArgNum, _MaxSize, CurSize, NewSize,
+args_to_string_verbose_list([], _ArgNum, _MaxSize, CurSize, NewSize,
 		_MaxDepth, _CurDepth, []) :-
 	NewSize = CurSize.
-
-term_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
+args_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
 		MaxDepth, CurDepth, Frame) :-
-	term_to_string_verbose_2(Univ, MaxSize, CurSize, NewSize,
-		MaxDepth, CurDepth, TreeFrame),
+	browser_term_to_string_verbose_2(plain_term(Univ), MaxSize,
+		CurSize, NewSize, MaxDepth, CurDepth, TreeFrame),
 	% XXX: ArgNumS must have fixed length 2.
 	string__int_to_string(ArgNum, ArgNumS),
 	string__append_list([ArgNumS, "-"], LastBranchS),
 	frame__hglue([LastBranchS], TreeFrame, Frame).
-
-term_to_string_verbose_list([Univ1, Univ2 | Univs], ArgNum, MaxSize, CurSize,
-		NewSize, MaxDepth, CurDepth, Frame) :-
-	term_to_string_verbose_2(Univ1, MaxSize, CurSize, NewSize1,
-		MaxDepth, CurDepth, TreeFrame),
+args_to_string_verbose_list([Univ1, Univ2 | Univs], ArgNum, MaxSize,
+		CurSize, NewSize, MaxDepth, CurDepth, Frame) :-
+	browser_term_to_string_verbose_2(plain_term(Univ1), MaxSize, CurSize,
+		NewSize1, MaxDepth, CurDepth, TreeFrame),
 	ArgNum1 is ArgNum + 1,
-	term_to_string_verbose_list([Univ2 | Univs], ArgNum1, MaxSize,
+	args_to_string_verbose_list([Univ2 | Univs], ArgNum1, MaxSize,
 		NewSize1, NewSize2, MaxDepth, CurDepth, RestTreesFrame),
 	NewSize = NewSize2,
 	% XXX: ArgNumS must have fixed length 2.
@@ -651,6 +812,7 @@
 	frame__vglue(TopFrame, RestTreesFrame, Frame).
 
 :- pred unlines(list(string)::in, string::out) is det.
+
 unlines([], "").
 unlines([Line | Lines], Str) :-
 	string__append(Line, "\n", NLine),
@@ -719,14 +881,51 @@
 
 	% We assume a root-relative path. We assume Term is the entire term
 	% passed into browse/3, not a subterm.
-:- pred deref_subterm(univ, list(dir), univ) is semidet.
-:- mode deref_subterm(in, in, out) is semidet.
-deref_subterm(Univ, Path, SubUniv) :-
+:- pred deref_subterm(browser_term::in, list(dir)::in, browser_term::out)
+	is semidet.
+
+deref_subterm(BrowserTerm, Path, SubBrowserTerm) :-
 	simplify_dirs(Path, SimplifiedPath),
-	deref_subterm_2(Univ, SimplifiedPath, SubUniv).
+	(
+		BrowserTerm = plain_term(Univ),
+		deref_subterm_2(Univ, SimplifiedPath, SubUniv),
+		SubBrowserTerm = plain_term(SubUniv)
+	;
+		BrowserTerm = synthetic_term(_Functor, Args, MaybeReturn),
+		(
+			SimplifiedPath = [],
+			SubBrowserTerm = BrowserTerm
+		;
+			SimplifiedPath = [Step | SimplifiedPathTail],
+			(
+				Step = child_num(N),
+				% The first argument of a non-array is numbered
+				% argument 1.
+				list__index1(Args, N, ArgUniv)
+			;
+				Step = child_name(Name),
+				(
+					MaybeReturn = yes(ArgUnivPrime),
+					( Name = "r"
+					; Name = "res"
+					; Name = "result"
+					)
+				->
+					ArgUniv = ArgUnivPrime
+				;
+					fail
+				)
+			;
+				Step = parent,
+				error("deref_subterm: found parent")
+			),
+			deref_subterm_2(ArgUniv, SimplifiedPathTail, SubUniv),
+			SubBrowserTerm = plain_term(SubUniv)
+		)
+	).
 
-:- pred deref_subterm_2(univ, list(dir), univ) is semidet.
-:- mode deref_subterm_2(in, in, out) is semidet.
+:- pred deref_subterm_2(univ::in, list(dir)::in, univ::out) is semidet.
+
 deref_subterm_2(Univ, Path, SubUniv) :-
 	(
 		Path = [],
@@ -782,19 +981,19 @@
 		list__append(PwdDirs, Dirs, NewDirs)
 	),
 	simplify_dirs(NewDirs, RootRelDirs).
+
+:- pred set_term(univ::in, browser_info::in, browser_info::out) is det.
 
-:- pred set_term(T, browser_info, browser_info).
-:- mode set_term(in, in, out) is det.
 set_term(Term, Info0, Info) :-
-	type_to_univ(Term, Univ),
-	set_univ(Univ, Info0, Info1),
+	set_browser_term(plain_term(Term), Info0, Info1),
 	% Display from the root term.
 	% This avoid errors due to dereferencing non-existent subterms.
 	set_path(root_rel([]), Info1, Info).
+
+:- pred set_browser_term(browser_term::in, browser_info::in, browser_info::out)
+	is det.
 
-:- pred set_univ(univ, browser_info, browser_info).
-:- mode set_univ(in, in, out) is det.
-set_univ(NewUniv, Info, Info ^ term := NewUniv).
+set_browser_term(BrowserTerm, Info, Info ^ term := BrowserTerm).
 
 %---------------------------------------------------------------------------%
 %
@@ -974,5 +1173,61 @@
 	write(Term),
 	print(".\n"),
 	flush_output.
+
+%---------------------------------------------------------------------------%
+
+    % These two functions are just like like pprint:to_doc, except their input
+    % is not a natural term, but a synthetic term defined by a functor, a list
+    % of arguments, and a boolean that is true iff the synthetic term is a
+    % function application, and thus should be printed not as f(a1, ... an)
+    % but as f(a1, ... an-1) = an.
+:- func synthetic_term_to_doc(string, list(univ), maybe(univ))      = doc.
+:- func synthetic_term_to_doc(int, string, list(univ), maybe(univ)) = doc.
+
+synthetic_term_to_doc(Functor, Args, MaybeReturn) =
+	synthetic_term_to_doc(int__max_int, Functor, Args, MaybeReturn).
+
+synthetic_term_to_doc(Depth, Functor, Args, MaybeReturn) = Doc :-
+	Arity = list__length(Args),
+	( Depth =< 0 ->
+		( Arity = 0 ->
+			Doc = text(Functor)
+		;
+			(
+				MaybeReturn = yes(_),
+				Doc = text(Functor) `<>` text("/") `<>`
+					poly(i(Arity)) `<>` text("+1") 
+			;
+				MaybeReturn = no,
+				Doc = text(Functor) `<>` text("/") `<>`
+					poly(i(Arity))
+			)
+		)
+	;
+		( Arity = 0 ->
+			Doc = text(Functor)
+		;
+			ArgDocs = packed_cs_univ_args(Depth - 1, Args),
+			(
+				MaybeReturn = yes(Return),
+				Doc = group(
+					text(Functor) `<>`
+					parentheses(
+						nest(2, ArgDocs)
+					) `<>`
+					nest(2, text(" = ") `<>`
+						to_doc(Depth - 1, Return)
+					)
+				)
+			;
+				MaybeReturn = no,
+				Doc = group(
+					text(Functor) `<>` parentheses(
+						nest(2, ArgDocs)
+					)
+				)
+			)
+		)
+	).
 
 %---------------------------------------------------------------------------%
Index: browser/browser_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/browser_info.m,v
retrieving revision 1.5
diff -u -b -r1.5 browser_info.m
--- browser/browser_info.m	2001/12/19 06:44:47	1.5
+++ browser/browser_info.m	2002/01/09 05:12:03
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 2000-2001 The University of Melbourne.
+% Copyright (C) 2000-2002 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.
 %---------------------------------------------------------------------------%
@@ -15,20 +15,36 @@
 :- interface.
 :- import_module bool, list, std_util.
 
+:- type browser_term
+	--->	plain_term(
+			univ		% We are browsing a plain term.
+		)
+	;	synthetic_term(
+			string,		% We are browsing a synthetic term,
+					% such as a predicate name applied to
+					% a list of arguments. The string says
+					% what we should print as the functor.
+			list(univ),	% The arguments.
+			maybe(univ)	% If yes, the synthetic term represents
+					% a function call, and the argument
+					% inside the yes() is the return value.
+		).
+
 	% The non-persistent browser information.  A new one of these is
 	% created every time the browser is called, based on the contents
 	% of the persistent state, and lasts for the duration of the call.
 	%
 :- type browser_info
 	--->	browser_info(
-			term	:: univ,	% Term to browse.
-			dirs	:: list(dir),	% The list of directories to
-						% take, starting from the root,
-						% to reach the current subterm.
+			term		:: browser_term,
+					% Term to browse.
+			dirs		:: list(dir),
+					% The list of directories to take,
+					% starting from the root, to reach
+					% the current subterm.
 			format	:: maybe(portray_format),
-						% Format specified as
-						% an option to the mdb
-						% command.
+					% Format specified as an option to the
+					% mdb command.
 			state	:: browser_persistent_state,
 						% Persistent settings.
 			maybe_mark :: maybe(list(dir))
@@ -84,9 +100,8 @@
 	% Initialise a new browser_info.  The optional portray_format
 	% overrides the default format.
 	%
-:- pred browser_info__init(T, maybe(portray_format), browser_persistent_state,
-		browser_info).
-:- mode browser_info__init(in, in, in, out) is det.
+:- func browser_info__init(browser_term, maybe(portray_format),
+	browser_persistent_state) = browser_info.
 
 	% Get the format to use for the given caller type.  The optional
 	% portray_format overrides the current default.
@@ -125,6 +140,24 @@
 
 %---------------------------------------------------------------------------%
 
+% These three predicates are like the deconstruct, limited_deconstruct and
+% functor procedures in std_util, except they work on browser_terms.
+% This requires them to have an extra argument (the last). For deconstruct
+% and limited_deconstruct, this returns the return value if the browser term
+% represents a function call. For functor, it says whether the browser term
+% represents a function call.
+
+:- pred deconstruct_browser_term(browser_term::in,
+	string::out, int::out, list(univ)::out, maybe(univ)::out) is det.
+
+:- pred limited_deconstruct_browser_term(browser_term::in, int::in,
+	string::out, int::out, list(univ)::out, maybe(univ)::out) is semidet.
+
+:- pred functor_browser_term(browser_term::in, string::out, int::out,
+	bool::out) is det.
+
+%---------------------------------------------------------------------------%
+
 :- implementation.
 :- import_module require.
 
@@ -199,8 +232,8 @@
 
 %---------------------------------------------------------------------------%
 
-browser_info__init(Term, MaybeFormat, State, Info) :-
-	Info = browser_info(univ(Term), [], MaybeFormat, State, no).
+browser_info__init(BrowserTerm, MaybeFormat, State) =
+	browser_info(BrowserTerm, [], MaybeFormat, State, no).
 
 browser_info__get_format(Info, Caller, MaybeFormat, Format) :-
 	(
@@ -413,3 +446,45 @@
 browser_persistent_state_type(type_of(State)) :-
 	browser_info__init_persistent_state(State).
 
+%---------------------------------------------------------------------------%
+
+deconstruct_browser_term(BrowserTerm, Functor, Arity, Args, MaybeReturn) :-
+	(
+		BrowserTerm = plain_term(Univ),
+		deconstruct(univ_value(Univ), Functor, Arity, Args),
+		MaybeReturn = no
+	;
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		list__length(Args, Arity)
+	).
+
+limited_deconstruct_browser_term(BrowserTerm, Limit, Functor, Arity, Args,
+		MaybeReturn) :-
+	(
+		BrowserTerm = plain_term(Univ),
+		limited_deconstruct(univ_value(Univ), Limit,
+			Functor, Arity, Args),
+		MaybeReturn = no
+	;
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		list__length(Args, Arity)
+	).
+
+functor_browser_term(BrowserTerm, Functor, Arity, IsFunc) :-
+	(
+		BrowserTerm = plain_term(Univ),
+		functor(univ_value(Univ), Functor, Arity),
+		IsFunc = no
+	;
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		list__length(Args, Arity),
+		(
+			MaybeReturn = yes(_),
+			IsFunc = yes
+		;
+			MaybeReturn = no,
+			IsFunc = no
+		)
+	).
+
+%---------------------------------------------------------------------------%
Index: browser/sized_pretty.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/sized_pretty.m,v
retrieving revision 1.4
diff -u -b -r1.4 sized_pretty.m
--- browser/sized_pretty.m	2001/06/26 06:16:22	1.4
+++ browser/sized_pretty.m	2002/01/09 05:45:21
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 2001 The University of Melbourne.
+% Copyright (C) 2001-2002 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.
 %---------------------------------------------------------------------------%
@@ -161,12 +161,20 @@
 
 :- interface.
 
+:- import_module mdb__browser_info.
 :- import_module std_util, int, string.
 
-	% This may throw an exception or cause a runtime abort if the term
-	% in question has user-defined equality. 
-	% The Limit is number of lines.
-:- pred univ_to_string_line(univ::in, int::in, int::in, string::out) is det.
+	% sized_pretty__univ_to_string_line(Univ, LineWidth, Lines, String)
+	% Converts the term in Univ to a string that fits into Lines lines
+	% of width LineWidth. It may throw an exception or cause a runtime
+	% abort if the term in question has no canonical representation.
+:- pred sized_pretty__univ_to_string_line(univ::in, int::in, int::in,
+	string::out) is det.
+
+	% The same as sized_pretty__univ_to_string_line, except works on
+	% browser_terms.
+:- pred sized_pretty__browser_term_to_string_line(browser_term::in,
+	int::in, int::in, string::out) is det.
 
 %---------------------------------------------------------------------------%
 
@@ -192,16 +200,17 @@
 	% upto the point where the specified limit was reached.
 :- type size_annotated_term(T)
 	--->	exact(
-			univ,			% univ(Term)
+			browser_term,		% univ(Term)
 			T,			% size of the term
 			string,			% Functor
 			int,			% Arity
 			size_annotated_args(T) 	% arguments
 		)
 	;	at_least(
-			univ,		% univ(Term)
-			T,		% size of the term upto the point
-					% where it's deconstructed
+			browser_term,		% univ(Term)
+			T,			% size of the term up to the
+						% point where it is
+						% deconstructed
 			maybe_deconstructed(T)
 		).
 
@@ -238,24 +247,32 @@
 		%	  each argument,
 		%	- adjusted measurement of available space,
 		%	- adjusted measure parameter(s).
-	pred measured_split(univ::in, MeasureParams::in, T::in, int::in,
-	     bool::in, T::out, maybe(T)::out, T::out, MeasureParams::out) is det
-		
+	pred measured_split(browser_term::in, MeasureParams::in, T::in,
+		int::in, bool::in, T::out, maybe(T)::out, T::out,
+		MeasureParams::out) is det
 ].
 
 %---------------------------------------------------------------------------%
+
 	% When the space (to print the term) is given in number of lines there
-	% is an inital check that has to be done. This is due to the fact that
+	% is an initial check that has to be done. This is due to the fact that
 	% size_count_split assumes that every term is part of a bigger term and
 	% therefore assumes that a term will have a comma and a space after it.
 	% This is not true for the biggest term (Head Term) therefore if the
 	% Head Term is going to be printed on a single line then it should be
 	% given a limit of character_count(LineWidth - 1) instead of
 	% character_count(LineWidth - 3).
-univ_to_string_line(Univ, LineWidth, Lines, String) :-
+
+sized_pretty__univ_to_string_line(Univ, LineWidth, Lines, String) :-
+	sized_pretty__browser_term_to_string_line(plain_term(Univ),
+		LineWidth, Lines, String).
+
+sized_pretty__browser_term_to_string_line(BrowserTerm, LineWidth, Lines,
+		String) :-
 	Params = measure_params(LineWidth),
-	functor(univ_value(Univ), _, Arity),
-	( 	Arity \= 0,
+	functor_browser_term(BrowserTerm, _Functor, Arity, _MaybeReturn),
+	(
+		Arity \= 0,
 		Lines \= 0,
 		(Lines - 1) // Arity = 0 
 	->
@@ -264,60 +281,63 @@
 	;
 		Limit = line_count(Lines)
 	),
-	annotate_with_size(Univ, Params, Limit, AnnotTerm),
+	annotate_with_size(BrowserTerm, Params, Limit, AnnotTerm),
 	Doc = to_doc_sized(AnnotTerm),
 	String = pprint__to_string(LineWidth, Doc).
 
 %---------------------------------------------------------------------------%
+
 	% first_pass gives an idea of how much space each term takes
 	% In this pass the space is unevenly distributed. First come first
 	% served. And once the space runs out, the term is not deconstructed
 	% further. 
-	% In The Second pass the space is evenly distributed between
+	% In the Second pass the space is evenly distributed between
 	% the terms and therefore the subterms are deconstructed evenly.
-:- pred annotate_with_size(univ::in, MeasureParams::in, T::in,
+:- pred annotate_with_size(browser_term::in, MeasureParams::in, T::in,
 	size_annotated_term(T)::out) is det
 	<= measure_with_params(T, MeasureParams).
 
-annotate_with_size(Univ, Params, Limit, Size2) :-
-	first_pass(Univ, Params, Limit, Size1),
-	second_pass(Size1, Params, Limit, Size2).
+annotate_with_size(BrowserTerm, Params, Limit, SizedTerm2) :-
+	first_pass(BrowserTerm, Params, Limit, SizedTerm1),
+	second_pass(SizedTerm1, Params, Limit, SizedTerm2).
 
 %---------------------------------------------------------------------------%
 	
-:- pred first_pass(univ::in, MeasureParams::in, T::in,
+:- pred first_pass(browser_term::in, MeasureParams::in, T::in,
 	size_annotated_term(T)::out) is det
 	<= measure_with_params(T, MeasureParams).
 
-first_pass(Univ, Params, Limit, Size) :-
+first_pass(BrowserTerm, Params, Limit, Size) :-
 	MaxFunctors = maximum_functors(Limit, Params),
 	(
-		limited_deconstruct(univ_value(Univ), MaxFunctors,
-				Functor, Arity, UnivArgs)
+		limited_deconstruct_browser_term(BrowserTerm, MaxFunctors,
+			Functor, Arity, Args, _MaybeReturn)
 	->
-		measured_split(Univ, Params, Limit, Arity, yes, FunctorSize, 
-					MaybeInitArgLimit, NewLimit, NewParams),
+		measured_split(BrowserTerm, Params, Limit, Arity, yes,
+			FunctorSize, MaybeInitArgLimit, NewLimit, NewParams),
 		( (Arity \= 0, MaybeInitArgLimit = no) ->
 			Exact0 = no
 		;
 			Exact0 = yes
 		),
-		annotate_args_with_size(UnivArgs, MaybeInitArgLimit, NewParams,
+		annotate_args_with_size(Args, MaybeInitArgLimit, NewParams,
 			NewLimit, FunctorSize, SoFar, Exact0, Exact,
 			MaybeArgSizes),
 		(
 			Exact = no,
-			Size = at_least(Univ, SoFar,
+			Size = at_least(BrowserTerm, SoFar,
 				deconstructed(Functor, Arity, MaybeArgSizes))
 		;
 			Exact = yes,
-			Size = exact(Univ, SoFar, Functor, Arity, MaybeArgSizes)
+			Size = exact(BrowserTerm, SoFar, Functor, Arity,
+				MaybeArgSizes)
 		)
 	;
-		Size = at_least(Univ, zero_measure, not_deconstructed)
+		Size = at_least(BrowserTerm, zero_measure, not_deconstructed)
 	).
 
 %---------------------------------------------------------------------------%
+
 	% annotating the arguments.
 :- pred annotate_args_with_size(list(univ)::in, maybe(T)::in,
 	MeasureParams::in, T::in, T::in, T::out, bool::in, bool::out, 
@@ -336,7 +356,7 @@
 			AppliedArgLimit = max_measure(InitArgLimit,
 				subtract_measures(Limit, SoFar0, Params))
 		),
-		first_pass(Arg, Params, AppliedArgLimit, Size),
+		first_pass(plain_term(Arg), Params, AppliedArgLimit, Size),
 		MaybeArgSize = yes(InitArgLimit - Size),
 		extract_size_from_annotation(Size) = ArgSize,
 		SoFar1 = add_measures(SoFar0, ArgSize, Params),
@@ -370,15 +390,19 @@
 
 %---------------------------------------------------------------------------%
 
-:- func extract_univ_from_annotation(size_annotated_term(T)) = univ.
+:- func extract_browser_term_from_annotation(size_annotated_term(T)) =
+	browser_term.
 
-extract_univ_from_annotation(exact(Univ, _, _, _, _)) = Univ.
-extract_univ_from_annotation(at_least(Univ, _, _)) = Univ.
+extract_browser_term_from_annotation(exact(BrowserTerm, _, _, _, _)) =
+	BrowserTerm.
+extract_browser_term_from_annotation(at_least(BrowserTerm, _, _)) =
+	BrowserTerm.
 
 %---------------------------------------------------------------------------%
+
 	% This predicate basically ensures that the arguments that
 	% take up smaller "Space" than their fair share is fully
-	% printed and the rest the Space is shared equally between
+	% printed and the rest of Space is shared equally between
 	% the other terms which could take up more than their share.
 	% If a term can be fully printed within the given space,
 	% ("exact" type) then the Term is not altered.
@@ -388,24 +412,25 @@
 
 second_pass(OldSizeTerm, Params, Limit, NewSizeTerm) :-
 	(
-    		OldSizeTerm = exact(_Univ, _Size, _, _Arity, _MaybeArgs),
+    		OldSizeTerm = exact(_BrowserTerm, _Size, _,
+			_Arity, _MaybeArgs),
 		NewSizeTerm = OldSizeTerm
 	;
-    		OldSizeTerm = at_least(_Univ, _Size, not_deconstructed),
+    		OldSizeTerm = at_least(_BrowserTerm, _Size, not_deconstructed),
 		NewSizeTerm = OldSizeTerm
 	;
-    		OldSizeTerm = at_least(Univ, _Size, deconstructed(Functor, 
-			Arity,MaybeArgs)),
-		measured_split(Univ, Params, Limit, Arity, yes, FSize,
+    		OldSizeTerm = at_least(BrowserTerm, _Size,
+			deconstructed(Functor, Arity,MaybeArgs)),
+		measured_split(BrowserTerm, Params, Limit, Arity, yes, FSize,
 			MaybeInitLimit, NewLimit, NewParams),
-		( if MaybeInitLimit = yes(InitLimit) then
+		( MaybeInitLimit = yes(InitLimit) ->
 	    		check_args(NewParams, MaybeArgs, InitLimit, Passed, 
 				FSize, Used),
 			LeftOver = add_measures(subtract_measures(NewLimit, 
 			  	Used, Params), FSize, Params),
-	    		measured_split(Univ, Params, LeftOver, Arity - Passed, 
-				no, _, MaybeSplitLimit, _, _),
-	    		( if MaybeSplitLimit = yes(SplitLimit) then
+	    		measured_split(BrowserTerm, Params, LeftOver,
+				Arity - Passed, no, _, MaybeSplitLimit, _, _),
+	    		( MaybeSplitLimit = yes(SplitLimit) ->
 	        		process_args(NewParams, MaybeArgs, InitLimit,
 					SplitLimit, NewArgs, NewSize0),
 				NewSize = add_measures(FSize, NewSize0, 
@@ -413,54 +438,60 @@
 				Result0 = list__map(check_if_exact, NewArgs),
     				list__remove_adjacent_dups(Result0, Result),
 				( Result = [yes] ->
-					NewSizeTerm = exact(Univ, NewSize, 
-						Functor, Arity, NewArgs) 	
+					NewSizeTerm = exact(BrowserTerm,
+						NewSize, Functor, Arity,
+						NewArgs) 	
 	        		;
-					NewSizeTerm = at_least(Univ, NewSize, 
+					NewSizeTerm = at_least(BrowserTerm,
+						NewSize, 
 						deconstructed(Functor, Arity, 
 						NewArgs))
 				)
-	    		else
-	        		NewSizeTerm = at_least(Univ, FSize, 
+	    		;
+	        		NewSizeTerm = at_least(BrowserTerm, FSize, 
 					not_deconstructed)
 	    		)
-		else
-			NewSizeTerm = at_least(Univ, FSize, not_deconstructed)
+		;
+			NewSizeTerm = at_least(BrowserTerm, FSize,
+				not_deconstructed)
 		)
 	).
 	
 %---------------------------------------------------------------------------%
+
 	% Given a list of size annotated terms(ie arguments) and a
 	% Limit, this predicate returns the values "Passed" and 
 	% "Used". Where "Passed" represents the number of terms that
 	% obey the Limit and are fully represented("exact") and "Used"
 	% represents the space that these terms take up.
 :- pred check_args(MeasureParams::in, size_annotated_args(T)::in, T::in, 
-	int::out, T::in, T::out) is det <= measure_with_params(T, 
-	MeasureParams).
+	int::out, T::in, T::out) is det
+	<= measure_with_params(T, MeasureParams).
 
 check_args(_, [], _, 0, Used0, Used0).
 check_args(Params, [HeadArg | Rest], ArgLimit, Passed, Used0, Used) :-
-	if HeadArg = yes(X) then
+	( HeadArg = yes(X) ->
 		X = _ - STerm,
 		Size = extract_size_from_annotation(STerm), 
-		( if STerm = exact(_, _, _, _, _) then
-	    		( if compare_measures(ArgLimit, Size) = (<) then
+		( STerm = exact(_, _, _, _, _) ->
+	    		( compare_measures(ArgLimit, Size) = (<) ->
 	    			check_args(Params, Rest, ArgLimit, Passed, 
 					Used0, Used)
-	    		else
+	    		;
 	    			Passed = 1 + PassedRest,
 				UsedSofar = add_measures(Used0, Size, Params),
 	    			check_args(Params, Rest, ArgLimit, PassedRest, 
 					UsedSofar, Used)
 	    		)
-		else
+		;
 	    		check_args(Params, Rest, ArgLimit, Passed, Used0, Used)
 		)
-    	else
-		check_args(Params, Rest, ArgLimit, Passed, Used0, Used).
+    	;
+		check_args(Params, Rest, ArgLimit, Passed, Used0, Used)
+	).
 
 %---------------------------------------------------------------------------%
+
 	% This predicate accepts a list of size annotated terms(paired
 	% with a flag) and returns a list of the same type. This new
 	% list would consist of the same number of terms as the other
@@ -474,10 +505,10 @@
 process_args(_, [], _, _, [], zero_measure).
 process_args(Params, [HeadArg | Rest], ArgLimit, SplitLimit, 
 		[NewHeadArg | NewRest], SizeOut) :-
-    	( if HeadArg = yes(X) then
+    	( HeadArg = yes(X) ->
 		X = _ - STerm,
 		Size = extract_size_from_annotation(STerm), 
-        	Univ = extract_univ_from_annotation(STerm), 
+        	BrowserTerm = extract_browser_term_from_annotation(STerm), 
 		( 
 			STerm = exact(_, _, _, _, _),
 	    		(
@@ -489,9 +520,10 @@
 			NewHeadArg = HeadArg
 		;
 			NewHeadArg = yes(pair(SplitLimit, NewSTerm)),
-			annotate_with_size(Univ, Params, SplitLimit, NewSTerm)
+			annotate_with_size(BrowserTerm, Params, SplitLimit,
+				NewSTerm)
 		)
-    	else
+    	;
 		NewHeadArg = no
     	),
     	( NewHeadArg = yes(_ - Term) ->
@@ -503,6 +535,7 @@
     	process_args(Params, Rest, ArgLimit, SplitLimit, NewRest, RestSize).
 
 %---------------------------------------------------------------------------%
+
 	% checking if an size-annotated arg is an exact type (fully represented)
 :- func check_if_exact(maybe(pair(T, size_annotated_term(T)))) = bool.
 
@@ -517,13 +550,28 @@
 	).	
 
 %---------------------------------------------------------------------------%
+
 	% A function to convert a size annotated term to a 'doc' type,
 	% a type defined in pprint.m.
 :- func to_doc_sized(size_annotated_term(T)) = doc.
 
-to_doc_sized(at_least(Univ, _, not_deconstructed)) = Doc :-
+to_doc_sized(at_least(BrowserTerm, _, not_deconstructed)) = Doc :-
+	(
+		BrowserTerm = plain_term(Univ),
 	functor(univ_value(Univ), Functor, Arity),
-	Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity)).
+		Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity))
+	;
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		list__length(Args, Arity),
+		(
+			MaybeReturn = yes(_),
+			Doc = text(Functor) `<>` text("/") `<>`
+				poly(i(Arity)) `<>` text("+1")
+		;
+			MaybeReturn = no,
+			Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity))
+		)
+	).
 
 to_doc_sized(at_least(_, _, deconstructed(Functor, Arity, MaybeArgs))) = Doc :-
 	Doc = to_doc_sized_2(Functor, Arity, MaybeArgs).
@@ -532,6 +580,7 @@
 	Doc = to_doc_sized_2(Functor, Arity, MaybeArgs).
 
 %---------------------------------------------------------------------------%
+
 	% Assumes that every argument must be on a different line
 	% or all of them should be on the same line.
 :- func to_doc_sized_2(string, int, size_annotated_args(T)) = doc.
@@ -556,6 +605,7 @@
 handle_arg(no) = nil.
 
 %---------------------------------------------------------------------------%
+
 	% functor_count is a representation where the size of a term
 	% is measured by the number of function symbols.
 
@@ -591,16 +641,18 @@
 
 zero_functor_count = functor_count(0).
 	
-:- pred functor_count_split(univ::in, no_measure_params::in, functor_count::in,
-	int::in, bool::in, functor_count::out, maybe(functor_count)::out,
-	functor_count::out, no_measure_params::out) is det.
+:- pred functor_count_split(browser_term::in, no_measure_params::in,
+	functor_count::in, int::in, bool::in, functor_count::out,
+	maybe(functor_count)::out, functor_count::out, no_measure_params::out)
+	is det.
 
-functor_count_split(_, Params, functor_count(Limit), Arity, _, functor_count(1),
-		MaybeArgLimit, functor_count(Limit), Params) :-
+functor_count_split(_, Params, functor_count(Limit), Arity, _,
+		functor_count(1), MaybeArgLimit, functor_count(Limit),
+		Params) :-
 	( Arity = 0 ->
 		MaybeArgLimit = no
 	;
-		( Limit =< (Arity + 1) ->			
+		( Limit =< Arity + 1 ->			
 			MaybeArgLimit = no
 		;
 			RoundUp = (Limit + Arity - 1) // Arity,
@@ -621,8 +673,8 @@
 	pred(measured_split/9) is functor_count_split
 ].
 
-
 %---------------------------------------------------------------------------%
+
 	% char_count is a representation where the size of a term is
 	% measured by the number of characters.
 
@@ -659,21 +711,29 @@
 
 zero_char_count = char_count(0).
 
-:- pred char_count_split(univ::in, no_measure_params::in, char_count::in,
-	int::in, bool::in, char_count::out, maybe(char_count)::out,
-	char_count::out, no_measure_params::out) is det.
+:- pred char_count_split(browser_term::in, no_measure_params::in,
+	char_count::in, int::in, bool::in, char_count::out,
+	maybe(char_count)::out, char_count::out, no_measure_params::out)
+	is det.
 
-char_count_split(Univ, Params, char_count(Limit), Arity, Check, 
+char_count_split(BrowserTerm, Params, char_count(Limit), Arity, Check, 
 		char_count(FunctorSize), MaybeArgLimit, char_count(Limit),
 		Params) :-
-
-	deconstruct(univ_value(Univ), Functor, _, Args),
+	deconstruct_browser_term(BrowserTerm, Functor, _, Args, MaybeReturn),
 	( Check = yes ->
 		get_arg_length(Args, TotalLength, _)
 	;
 		TotalLength = 0
+	),
+	(
+		MaybeReturn = yes(_),
+		% Arity-1 times the string ", ", once "()", and once " = "
+		FunctorSize = string__length(Functor) + 2 * Arity + 3
+	;
+		MaybeReturn = no,
+		% Arity-1 times the string ", ", and once "()"
+		FunctorSize = string__length(Functor) + 2 * Arity
 	),
-	FunctorSize = string__length(Functor) + 2*(Arity),
 	( Arity = 0 ->
 		MaybeArgLimit = no
 	;
@@ -699,6 +759,7 @@
 ].
 
 %---------------------------------------------------------------------------%
+
 	% size_count is representation where the size of a term is
 	% measured by number of lines or number of characters.
 
@@ -821,26 +882,26 @@
 
 	% We assume that all arguments have to be on separate lines, or 
 	% the whole term should be printed on a single line.
-:- pred size_count_split(univ::in, measure_params::in, size_count::in,
+:- pred size_count_split(browser_term::in, measure_params::in, size_count::in,
 	int::in, bool::in, size_count::out, maybe(size_count)::out,
 	size_count::out, measure_params::out) is det.
 
-size_count_split(Univ, Params, Limit, Arity, Check, FunctorSize, 
+size_count_split(BrowserTerm, Params, Limit, Arity, Check, FunctorSize, 
 		MaybeArgLimit, NewLimit, NewParams) :-
 	% LineWidth is length of the line in which the functor is printed.
 	Params = measure_params(LineWidth),
-    	deconstruct(univ_value(Univ), Functor, ActualArity, Args),
+	deconstruct_browser_term(BrowserTerm, Functor, ActualArity, Args,
+		MaybeReturn),
     	FSize = string__length(Functor) + 2 * (ActualArity),
     	( Check = yes ->
     		get_arg_length(Args, TotalLength, MaxArgLength),
-		int__max(MaxArgLength, (string__length(Functor) + 1), MaxLength)
+		int__max(MaxArgLength, (string__length(Functor) + 1),
+			MaxLength)
     	;
     		TotalLength = 0,
 		MaxLength = 0
     	), 
-    	( 
-		Arity = 0 
-	->
+	( Arity = 0 ->
 		MaybeArgLimit = no,
     		FunctorSize = character_count(FSize),
 		NewLimit = Limit,
@@ -851,8 +912,8 @@
 			% we need one line for the functor and atleast 
 			% one line for each argument
 			LineLimit >= (Arity + 1),
-			% linewidth is decreased by two characters to account 
-			% for indentation
+			% linewidth is decreased by two characters
+			% to account  for indentation
 			(LineWidth - 2) >= MaxLength
 		->
 			Line = (LineLimit - 1) // Arity,
@@ -863,13 +924,15 @@
 		;
 			Limit = line_count(LineLimit),
 			LineLimit > 0,
-			% Since every term is part of a bigger term (in this 
-			% context anyway) it will have a comma, space and a 
-			% newline at the end of it (Hence the "- 3").
+			% Since every term is part of a bigger term
+			% (in this  context anyway) it will have a
+			% comma, space and a  newline at the end of it
+			% (Hence the "- 3").
 			LineWidth - 3 >= (FSize + TotalLength) 
 		->
 	    		% "Arity - 1" is for rounding up.
-			Char = (LineWidth - 3 - FSize + Arity - 1) // Arity ,
+			Char = (LineWidth - 3 - FSize + Arity - 1)
+				// Arity ,
 	    		MaybeArgLimit = yes(character_count(Char)),
 	    		FunctorSize = character_count(FSize),
 	    		NewLimit = character_count(LineWidth - 3),
@@ -878,17 +941,30 @@
 			Limit = character_count(CharLimit),
 			CharLimit >= (FSize + TotalLength)
 		->
-	   		Char = (CharLimit - FSize + Arity - 1) // Arity,
+			Char = (CharLimit - FSize + Arity - 1)
+				// Arity,
 	   		MaybeArgLimit = yes(character_count(Char)),
 	   		FunctorSize = character_count(FSize),
 	   		NewLimit = Limit,
 	   		NewParams = Params
 		;
 	   		MaybeArgLimit = no,
-			% If a term is not deconstructed, it is printed as
-			% "functor/Arity". The "+ 2" accounts for that.
-	   		FunctorSize = 
-				character_count(string__length(Functor) + 2),
+			% If an ordinary term is not deconstructed, it is
+			% printed as "functor/Arity". If a synthetic function
+			% term is not deconstructed, it is printed as
+			% "functor/Arity+1".
+			(
+				MaybeReturn = yes(_),
+				FuncSuffixChars = 2
+			;
+				MaybeReturn = no,
+				FuncSuffixChars = 0
+			),
+			FunctorLength = string__length(Functor),
+			string__int_to_string(Arity, ArityStr),
+			string__length(ArityStr, ArityChars),
+			FunctorSize = character_count(FunctorLength + 1
+				+ ArityChars + FuncSuffixChars),
 	   		NewLimit = Limit, 
 	   		NewParams = Params
 		)
@@ -908,6 +984,7 @@
 ].
 
 %---------------------------------------------------------------------------%
+
 	% This predicate determines how many characters it will take
 	% to print the functors of the arguments. Also determines the
 	% length of biggest functor.
Index: browser/util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/util.m,v
retrieving revision 1.13
diff -u -b -r1.13 util.m
--- browser/util.m	2001/06/22 15:20:23	1.13
+++ browser/util.m	2002/01/08 08:57:39
@@ -74,6 +74,10 @@
 :- pred util__limit(pred(list(T), list(T)), list(T), list(T)).
 :- mode util__limit(pred(in,out) is det, in, out) is det.
 
+	% For use in representing unbound head variables in the "print goal"
+	% commands in the debugger.
+:- type unbound ---> '_'.
+
 %---------------------------------------------------------------------------%
 :- implementation.
 
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.284
diff -u -b -r1.284 user_guide.texi
--- doc/user_guide.texi	2002/01/07 07:48:10	1.284
+++ doc/user_guide.texi	2002/01/09 06:57:02
@@ -2163,6 +2163,13 @@
 The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
 and @samp{-v} or @samp{--verbose} specify the format to use for printing.
 @sp 1
+ at item print [-fpv]
+ at item print [-fpv] goal
+Prints the goal of the current call in its present state of instantiation.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for printing.
+ at sp 1
 @item print [-fpv] exception
 Prints the value of the exception at an EXCP port.
 Reports an error if the current event does not refer to such a port.
@@ -2190,6 +2197,14 @@
 For further documentation on the interactive term browser,
 invoke the @samp{browse} command from within @samp{mdb} and then
 type @samp{help} at the @samp{browser>} prompt.
+ at sp 1
+ at item browse [-fpv]
+ at item browse [-fpv] goal
+Invokes the interactive term browser to browse
+the goal of the current call in its present state of instantiation.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for browsing.
 @sp 1
 @item browse [-fpv] exception
 Invokes the interactive term browser to browse
Index: library/pprint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.7
diff -u -b -r1.7 pprint.m
--- library/pprint.m	2002/01/02 04:14:11	1.7
+++ library/pprint.m	2002/01/02 04:31:04
@@ -150,7 +150,7 @@
 
 :- interface.
 
-:- import_module int, string, list, io.
+:- import_module std_util, int, string, list, io.
 
     % Clients must translate data structures into docs for
     % the pretty printer to display.
@@ -250,6 +250,16 @@
     %
 :- func packed_cs(int, list(doc)) = doc.
 
+    % This is like a depth-limited version of packed_cs/1 that first
+    % calls to_doc/2 on each member of the argument list.
+    %
+:- func packed_cs_to_depth(int, list(T)) = doc.
+
+    % This is like a version of packed_cs_to_depth/1 that first
+    % calls univ_value/1 for each member of the argument list.
+    %
+:- func packed_cs_univ_args(int, list(univ)) = doc.
+
     % separated(PP, Sep, [X1,...,Xn]) =
     %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
     %
@@ -312,7 +322,7 @@
 
 :- implementation.
 
-:- import_module std_util, char, array, map.
+:- import_module char, array, map.
 
 :- type doc
     --->    'NIL'
@@ -526,20 +536,10 @@
 
 %------------------------------------------------------------------------------%
 
-    % This is like a depth-limited version of packed_cs/1 that first
-    % calls to_doc/2 on each member of the argument list.
-    %
-:- func packed_cs_to_depth(int, list(T)) = doc.
-
 packed_cs_to_depth(Depth, Xs) =
     packed_cs(Depth, list__map(to_doc(Depth), Xs)).
 
 %------------------------------------------------------------------------------%
-
-    % This is like a version of packed_cs_to_depth/1 that first
-    % calls univ_value/1 for each member of the argument list.
-    %
-:- func packed_cs_univ_args(int, list(univ)) = doc.
 
 packed_cs_univ_args(Depth, UnivArgs) = 
     packed_cs(
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.78
diff -u -b -r1.78 mercury_type_info.h
--- runtime/mercury_type_info.h	2002/01/11 04:43:32	1.78
+++ runtime/mercury_type_info.h	2002/01/11 06:04:23
@@ -292,6 +292,33 @@
 #define MR_fill_in_tuple_type_info(arena, type_ctor_info, arity, vector) \
     MR_fill_in_higher_order_type_info(arena, type_ctor_info, arity, vector)
 
+#define MR_static_type_info_arity_0(name, ctor)				\
+	struct {							\
+		MR_TypeCtorInfo field1;					\
+	} name = {							\
+		(MR_TypeCtorInfo) (ctor)				\
+	};
+
+#define MR_static_type_info_arity_1(name, ctor, ti1)			\
+	struct {							\
+		MR_TypeCtorInfo field1;					\
+		MR_TypeInfo 	field2;					\
+	} name = {							\
+		(MR_TypeCtorInfo) (ctor),				\
+		(MR_TypeInfo)     (ti1)					\
+	};
+
+#define MR_static_type_info_arity_2(name, ctor, ti1, ti2)		\
+	struct {							\
+		MR_TypeCtorInfo field1;					\
+		MR_TypeInfo 	field2;					\
+		MR_TypeInfo 	field3;					\
+	} name = {							\
+		(MR_TypeCtorInfo) (ctor),				\
+		(MR_TypeInfo)     (ti1),				\
+		(MR_TypeInfo)     (ti2)					\
+	};
+
 /*
 ** Used to define MR_TypeCtorInfos for the builtin types in the hlc grades.
 ** This needs to be exported for use by the array type in the library.
@@ -299,6 +326,9 @@
 
 #ifdef MR_HIGHLEVEL_CODE
 
+  #define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
+		MR_type_ctor_info_name(builtin, TYPE, ARITY)
+
   #define MR_type_ctor_info_name(MODULE, TYPE, ARITY)			      \
 	MR_PASTE2(mercury__,						      \
 	MR_PASTE2(MODULE,						      \
@@ -346,6 +376,23 @@
 		-1							      \
 	}
 
+#else /* MR_HIGHLEVEL_CODE */
+
+  #define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
+	MR_PASTE2(mercury_data_,					      \
+	MR_PASTE2(__type_ctor_info_,					      \
+	MR_PASTE2(TYPE,							      \
+	MR_PASTE2(_,							      \
+		 ARITY))))
+
+  #define MR_type_ctor_info_name(MODULE, TYPE, ARITY)			      \
+	MR_PASTE2(mercury_data_,					      \
+	MR_PASTE2(MODULE,						      \
+	MR_PASTE2(__type_ctor_info_,					      \
+	MR_PASTE2(TYPE,							      \
+	MR_PASTE2(_,							      \
+		 ARITY)))))
+
 #endif /* MR_HIGHLEVEL_CODE */
 
 /*---------------------------------------------------------------------------*/
@@ -362,15 +409,25 @@
 	** the same primary tag (1), and are all allocated secondary tags
 	** starting from 0.
 	*/
-    #define MR_COMPARE_TAG      MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
+  #define MR_ENUM_TAG         MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
  
-    #define MR_COMPARE_EQUAL    MR_mkword(MR_COMPARE_TAG, MR_mkbody(0))
-    #define MR_COMPARE_LESS     MR_mkword(MR_COMPARE_TAG, MR_mkbody(1))
-    #define MR_COMPARE_GREATER  MR_mkword(MR_COMPARE_TAG, MR_mkbody(2))         
+  #define MR_COMPARE_EQUAL    MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
+  #define MR_COMPARE_LESS     MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
+  #define MR_COMPARE_GREATER  MR_mkword(MR_ENUM_TAG, MR_mkbody(2))         
+
+  #define MR_BOOL_NO          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
+  #define MR_BOOL_YES         MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
+
+  #define MR_UNBOUND          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
 #else
     #define MR_COMPARE_EQUAL    0
     #define MR_COMPARE_LESS     1
     #define MR_COMPARE_GREATER  2
+
+  #define MR_BOOL_NO          0
+  #define MR_BOOL_YES         1
+
+  #define MR_UNBOUND          0
 #endif
 
 /*---------------------------------------------------------------------------*/
Index: tests/debugger/browse_pretty.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browse_pretty.exp,v
retrieving revision 1.7
diff -u -b -r1.7 browse_pretty.exp
--- tests/debugger/browse_pretty.exp	2001/11/07 06:43:08	1.7
+++ tests/debugger/browse_pretty.exp	2002/01/09 05:48:20
@@ -104,5 +104,26 @@
   [|](1, [|](2, [|]/2)), 
   small)
 browser> quit
+mdb> print goal
+big_data(
+  big(big/3, [|]/2, big/3))
+mdb> browse goal
+browser> ls
+big_data(
+  big(big/3, [|]/2, big/3))
+browser> ^1
+browser> ls
+big(
+  big(big/3, [|]/2, small), 
+  [|](1, [|](2, [|]/2)), 
+  big(big/3, [|]/2, small))
+browser> ^..
+browser> ls
+big_data(
+  big(big/3, [|]/2, big/3))
+browser> ^1^2^2
+browser> ls
+[|](2, [|](3, []))
+browser> quit
 mdb> continue
 big(big(big(small, [1], small), [1, 2], small), [1, 2, 3], big(big(small, [1, 2, 3, 4], big(small, [1, 2, 3, 4, 5], small)), [1, 2, 3, 4, 5, 6], small)).
Index: tests/debugger/browse_pretty.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browse_pretty.inp,v
retrieving revision 1.3
diff -u -b -r1.3 browse_pretty.inp
--- tests/debugger/browse_pretty.inp	2001/02/23 04:15:16	1.3
+++ tests/debugger/browse_pretty.inp	2002/01/09 05:47:26
@@ -28,5 +28,14 @@
 set width 30
 ls
 quit
+print goal
+browse goal
+ls
+^1
+ls
+^..
+ls
+^1^2^2
+ls
+quit
 continue
-
Index: tests/debugger/polymorphic_output.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/polymorphic_output.exp,v
retrieving revision 1.4
diff -u -b -r1.4 polymorphic_output.exp
--- tests/debugger/polymorphic_output.exp	2002/01/11 04:21:26	1.4
+++ tests/debugger/polymorphic_output.exp	2002/01/11 04:49:50
@@ -4,6 +4,53 @@
 mdb> register --quiet
 mdb> context none
 Contexts will not be printed.
+mdb> b functor_names
+ 0: + stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> c
+       2:      2  2 CALL func polymorphic_output:functor_names/2-0 (det)
+mdb> delete 0
+ 0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> p goal
+functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
+mdb> set format verbose
+mdb> set lines 100
+mdb> p goal
+functor_names
+1-two
+| 1-"three"
+| 2-3
+| 3-three
+| | 1-"four"
+| | 2-4
+| | 3-"one"
+| | 4-1
+| | 5-empty
+| | 6-empty
+| | 7-empty
+| 4-two
+|   1-"two"
+|   2-2
+|   3-empty
+|   4-empty
+2-_
+
+mdb> set format flat
+mdb> browse goal
+browser> ^1
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^2
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^3
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^r
+browser> p
+'_'
+browser> quit
 mdb> b std_util__det_arg
 mdb: there is no such procedure.
 mdb> c
Index: tests/debugger/polymorphic_output.exp2
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/polymorphic_output.exp2,v
retrieving revision 1.6
diff -u -b -r1.6 polymorphic_output.exp2
--- tests/debugger/polymorphic_output.exp2	2002/01/11 04:21:27	1.6
+++ tests/debugger/polymorphic_output.exp2	2002/01/11 04:49:50
@@ -4,6 +4,37 @@
 mdb> register --quiet
 mdb> context none
 Contexts will not be printed.
+mdb> b functor_names
+ 0: + stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> c
+       4:      3  2 CALL func polymorphic_output:functor_names/2-0 (det)
+mdb> delete 0
+ 0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> p goal
+functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
+mdb> set format verbose
+mdb> set lines 100
+mdb> p goal
+functor_names
+1-two
+| 1-"three"
+| 2-3
+| 3-three
+| | 1-"four"
+| | 2-4
+| | 3-"one"
+| | 4-1
+| | 5-empty
+| | 6-empty
+| | 7-empty
+| 4-two
+|   1-"two"
+|   2-2
+|   3-empty
+|   4-empty
+2-_
+
+mdb> set format flat
 mdb> b std_util__det_arg
  0: + stop  interface func std_util:det_arg/3-0 (det)
 mdb> c
Index: tests/debugger/polymorphic_output.exp3
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/polymorphic_output.exp3,v
retrieving revision 1.2
diff -u -b -r1.2 polymorphic_output.exp3
--- tests/debugger/polymorphic_output.exp3	2002/01/11 04:21:27	1.2
+++ tests/debugger/polymorphic_output.exp3	2002/01/11 04:49:50
@@ -4,6 +4,53 @@
 mdb> register --quiet
 mdb> context none
 Contexts will not be printed.
+mdb> b functor_names
+ 0: + stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> c
+       2:      2  2 CALL func polymorphic_output:functor_names/2-0 (det)
+mdb> delete 0
+ 0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
+mdb> p goal
+functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
+mdb> set format verbose
+mdb> set lines 100
+mdb> p goal
+functor_names
+1-two
+| 1-"three"
+| 2-3
+| 3-three
+| | 1-"four"
+| | 2-4
+| | 3-"one"
+| | 4-1
+| | 5-empty
+| | 6-empty
+| | 7-empty
+| 4-two
+|   1-"two"
+|   2-2
+|   3-empty
+|   4-empty
+2-_
+
+mdb> set format flat
+mdb> browse goal
+browser> ^1
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^2
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^3
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^r
+browser> p
+'_'
+browser> quit
 mdb> b std_util__det_arg
 mdb: there is no such procedure.
 mdb> c
Index: tests/debugger/polymorphic_output.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/polymorphic_output.inp,v
retrieving revision 1.2
diff -u -b -r1.2 polymorphic_output.inp
--- tests/debugger/polymorphic_output.inp	2000/04/16 06:10:05	1.2
+++ tests/debugger/polymorphic_output.inp	2002/01/09 05:53:24
@@ -1,6 +1,24 @@
 echo on
 register --quiet
 context none
+b functor_names
+c
+delete 0
+p goal
+set format verbose
+set lines 100
+p goal
+set format flat
+browse goal
+^1
+p
+^..^2
+p
+^..^3
+p
+^..^r
+p
+quit
 b std_util__det_arg
 c
 P
Index: trace/mercury_trace_browse.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.c,v
retrieving revision 1.21
diff -u -b -r1.21 mercury_trace_browse.c
--- trace/mercury_trace_browse.c	2001/05/29 17:24:02	1.21
+++ trace/mercury_trace_browse.c	2002/01/07 01:15:20
@@ -86,6 +86,41 @@
 				MR_trace_browser_persistent_state_type);
 }
 
+void
+MR_trace_browse_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
+	MR_Browse_Format format)
+{
+	MercuryFile	mdb_in, mdb_out;
+	MR_Word		maybe_mark;
+
+	MR_trace_browse_ensure_init();
+
+	MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
+	MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
+
+	if (format != MR_BROWSE_DEFAULT_FORMAT) {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_browse_format_synthetic(
+				(MR_String) (MR_Word) name, arg_list, is_func,
+				(MR_Word) &mdb_in, (MR_Word) &mdb_out,
+				(MR_Word) format,
+				MR_trace_browser_persistent_state,
+				&MR_trace_browser_persistent_state);
+		);
+	} else {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_browse_synthetic(
+				(MR_String) (MR_Word) name, arg_list, is_func,
+				(MR_Word) &mdb_in, (MR_Word) &mdb_out,
+				&maybe_mark, MR_trace_browser_persistent_state,
+				&MR_trace_browser_persistent_state);
+		);
+	}
+	MR_trace_browser_persistent_state =
+		MR_make_permanent(MR_trace_browser_persistent_state,
+			MR_trace_browser_persistent_state_type);
+}
+
 /*
 ** MR_trace_browse_external() is the same as MR_trace_browse() except it 
 ** uses debugger_socket_in and debugger_socket_out to read program-readable 
@@ -135,6 +170,34 @@
 	} else {
 		MR_TRACE_CALL_MERCURY(
 			ML_BROWSE_print(type_info, value,
+				(MR_Word) &mdb_out, (MR_Word) caller,
+				MR_trace_browser_persistent_state);
+		);
+	}
+}
+
+void
+MR_trace_print_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
+	MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+	MercuryFile mdb_out;
+
+	MR_trace_browse_ensure_init();
+
+	MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
+
+	if (format != MR_BROWSE_DEFAULT_FORMAT) {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_print_format_synthetic(
+				(MR_String) (MR_Word) name, arg_list, is_func,
+				(MR_Word) &mdb_out, (MR_Word) caller,
+				(MR_Word) format,
+				MR_trace_browser_persistent_state);
+		);
+	} else {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_print_synthetic(
+				(MR_String) (MR_Word) name, arg_list, is_func,
 				(MR_Word) &mdb_out, (MR_Word) caller,
 				MR_trace_browser_persistent_state);
 		);
Index: trace/mercury_trace_browse.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.h,v
retrieving revision 1.13
diff -u -b -r1.13 mercury_trace_browse.h
--- trace/mercury_trace_browse.h	2001/06/02 09:35:12	1.13
+++ trace/mercury_trace_browse.h	2002/01/07 01:15:32
@@ -46,16 +46,21 @@
 */
 extern 	void	MR_trace_browse(MR_Word type_info, MR_Word value,
 			MR_Browse_Format format);
+extern 	void	MR_trace_browse_goal(MR_ConstString name, MR_Word arg_list,
+			MR_Word is_func, MR_Browse_Format format);
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 extern 	void	MR_trace_browse_external(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 #endif
 
 /*
-** Display a term (non-interactively).
+** Display a term non-interactively.
 */
 extern	void	MR_trace_print(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
+extern	void	MR_trace_print_goal(MR_ConstString name, MR_Word arg_list,
+			MR_Word is_func, MR_Browse_Caller_Type caller,
+			MR_Browse_Format format);
 
 /*
 ** Set browser parameters.
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.110
diff -u -b -r1.110 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	2001/12/11 09:01:24	1.110
+++ trace/mercury_trace_internal.c	2002/01/08 08:58:35
@@ -226,6 +226,9 @@
 			bool detailed);
 static	void	MR_trace_browse_internal(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
+static	void	MR_trace_browse_goal_internal(MR_ConstString name,
+			MR_Word arg_list, MR_Word is_func,
+			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 static	const char *MR_trace_browse_exception(MR_Event_Info *event_info,
 			MR_Browser browser, MR_Browse_Caller_Type caller,
 			MR_Browse_Format format);
@@ -500,6 +503,31 @@
 	}
 }
 
+static void
+MR_trace_browse_goal_internal(MR_ConstString name, MR_Word arg_list,
+	MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+	switch (caller) {
+		
+		case MR_BROWSE_CALLER_BROWSE:
+			MR_trace_browse_goal(name, arg_list, is_func, format);
+			break;
+
+		case MR_BROWSE_CALLER_PRINT:
+			MR_trace_print_goal(name, arg_list, is_func,
+				caller, format);
+			break;
+
+		case MR_BROWSE_CALLER_PRINT_ALL:
+			MR_fatal_error("MR_trace_browse_goal_internal:"
+				" bad caller type");
+
+		default:
+			MR_fatal_error("MR_trace_browse_goal_internal:"
+				" unknown caller type");
+	}
+}
+
 static const char *
 MR_trace_browse_exception(MR_Event_Info *event_info, MR_Browser browser,
 		MR_Browse_Caller_Type caller, MR_Browse_Format format)
@@ -1042,12 +1070,27 @@
 					"browsing", "print"))
 		{
 			; /* the usage message has already been printed */
+		} else if (word_count == 1) {
+			const char	*problem;
+
+			problem = MR_trace_browse_one_goal(MR_mdb_out,
+				MR_trace_browse_goal_internal,
+				MR_BROWSE_CALLER_PRINT, format);
+
+			if (problem != NULL) {
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+			}
 		} else if (word_count == 2) {
 			const char	*problem;
 
 			if (streq(words[1], "*")) {
 				problem = MR_trace_browse_all(MR_mdb_out,
 					MR_trace_browse_internal, format);
+			} else if (streq(words[1], "goal")) {
+				problem = MR_trace_browse_one_goal(MR_mdb_out,
+					MR_trace_browse_goal_internal,
+					MR_BROWSE_CALLER_PRINT, format);
 			} else if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
 					MR_trace_browse_internal,
@@ -1072,10 +1115,25 @@
 					"browsing", "browse"))
 		{
 			; /* the usage message has already been printed */
+		} else if (word_count == 1) {
+			const char	*problem;
+
+			problem = MR_trace_browse_one_goal(MR_mdb_out,
+				MR_trace_browse_goal_internal,
+				MR_BROWSE_CALLER_BROWSE, format);
+
+			if (problem != NULL) {
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+			}
 		} else if (word_count == 2) {
 			const char	*problem;
 
-			if (streq(words[1], "exception")) {
+			if (streq(words[1], "goal")) {
+				problem = MR_trace_browse_one_goal(MR_mdb_out,
+					MR_trace_browse_goal_internal,
+					MR_BROWSE_CALLER_BROWSE, format);
+			} else if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
 					MR_trace_browse_internal,
 					MR_BROWSE_CALLER_BROWSE, format);
Index: trace/mercury_trace_vars.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.c,v
retrieving revision 1.29
diff -u -b -r1.29 mercury_trace_vars.c
--- trace/mercury_trace_vars.c	2002/01/09 06:41:35	1.29
+++ trace/mercury_trace_vars.c	2002/01/09 06:57:12
@@ -656,6 +656,79 @@
 	return NULL;
 }
 
+/*
+** The following declaration allocates a cell to a typeinfo even if though
+** its arity is zero. This wastes a word of space but avoids depending on the
+** current typeinfo optimization scheme.
+*/
+
+MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_type_ctor_info_name(mdb__util, unbound, 0));
+static
+MR_static_type_info_arity_0(MR_unbound_typeinfo_struct,
+	&MR_type_ctor_info_name(mdb__util, unbound, 0));
+
+const char *
+MR_trace_browse_one_goal(FILE *out, MR_GoalBrowser browser,
+	MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+	const MR_Proc_Layout	*proc_layout;
+	MR_ConstString		proc_name;
+	MR_Word			is_func;
+	MR_Word			arg_list;
+	MR_Word			arg;
+	MR_TypeInfo		arg_list_typeinfo;
+	MR_Var_Details		*vars;
+	int			arity;
+	int			hv;
+	int			slot;
+
+	proc_layout = MR_point.MR_point_level_entry;
+	if (MR_PROC_LAYOUT_COMPILER_GENERATED(proc_layout)) {
+		proc_name = proc_layout->MR_sle_proc_id.
+			MR_proc_comp.MR_comp_pred_name;
+		arity = proc_layout->MR_sle_proc_id.
+			MR_proc_comp.MR_comp_arity;
+		is_func = MR_BOOL_NO;
+	} else {
+		proc_name = proc_layout->MR_sle_proc_id.
+			MR_proc_user.MR_user_name;
+		arity = proc_layout->MR_sle_proc_id.
+			MR_proc_user.MR_user_arity;
+		if (proc_layout->MR_sle_proc_id.MR_proc_user.
+				MR_user_pred_or_func == MR_FUNCTION)
+		{
+			is_func = MR_BOOL_YES;
+		} else {
+			is_func = MR_BOOL_NO;
+		}
+	}
+
+	vars = MR_point.MR_point_vars;
+	for (slot = MR_point.MR_point_var_count - 1; slot >= 0; slot--) {
+		if (vars[slot].MR_var_is_headvar) {
+			break;
+		}
+	}
+
+	arg_list = MR_list_empty();
+	for (hv = arity; hv >= 1; hv--) {
+		if (slot >= 0 && vars[slot].MR_var_is_headvar
+			&& vars[slot].MR_var_num_suffix == hv)
+		{
+			MR_new_univ_on_hp(arg, vars[slot].MR_var_type,
+				vars[slot].MR_var_value);
+			slot--;
+		} else {
+			MR_new_univ_on_hp(arg, &MR_unbound_typeinfo_struct,
+				MR_UNBOUND);
+		}
+		arg_list = MR_list_cons(arg, arg_list);
+	}
+
+	(*browser)(proc_name, arg_list, is_func, caller, format);
+	return NULL;
+}
+
 const char *
 MR_trace_parse_browse_one(FILE *out, char *word_spec, MR_Browser browser,
 	MR_Browse_Caller_Type caller, MR_Browse_Format format,
Index: trace/mercury_trace_vars.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.h,v
retrieving revision 1.13
diff -u -b -r1.13 mercury_trace_vars.h
--- trace/mercury_trace_vars.h	2001/12/04 00:44:40	1.13
+++ trace/mercury_trace_vars.h	2002/01/07 01:16:27
@@ -46,6 +46,11 @@
 typedef	void	(*MR_Browser)(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 
+typedef	void	(*MR_GoalBrowser)(MR_ConstString name, MR_Word arg_list,
+			MR_Word is_func, MR_Browse_Caller_Type caller,
+			MR_Browse_Format format);
+
+
 typedef	enum {
 	MR_VAR_SPEC_NUMBER,
 	MR_VAR_SPEC_NAME
@@ -101,6 +106,18 @@
 */
 
 extern	const char	*MR_trace_headvar_num(int n, int *num);
+
+/*
+** Print the call of the current level as a goal.
+**
+** The names are printed to the given file if the file pointer is non-NULL.
+** The goal is printed by giving it to the specified browser.
+*/
+
+extern	const char	*MR_trace_browse_one_goal(FILE *out,
+				MR_GoalBrowser browser,
+				MR_Browse_Caller_Type caller,
+				MR_Browse_Format format);
 
 /*
 ** Print the (names and) values of (the specified parts of) the specified

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

interdiff output follows:

diff -u NEWS NEWS
--- NEWS
+++ NEWS
@@ -156,6 +156,10 @@
 
 Changes to the Mercury implementation:
 
+* The debugger can now print goals just as Prolog debuggers do. At an exit
+  port of e.g. append, the command "print goal" will print the current goal
+  in a form such as "append([1], [2], [1, 2])".
+
 * You can now navigate terms in the debugger by argument name as well as by
   argument number.
 
diff -u browser/browse.m browser/browse.m
--- browser/browse.m
+++ browser/browse.m
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 1998-2001 The University of Melbourne.
+% Copyright (C) 1998-2002 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.
 %---------------------------------------------------------------------------%
@@ -21,7 +21,7 @@
 :- interface.
 
 :- import_module mdb__browser_info.
-:- import_module io, std_util, bool, list.
+:- import_module io, bool, std_util, list.
 
 	% The interactive term browser.  The caller type will be `browse', and
 	% the default format for the `browse' caller type will be used.
@@ -38,11 +38,17 @@
 			browser_persistent_state, io__state, io__state).
 :- mode browse__browse_format(in, in, in, in, in, out, di, uo) is det.
 
+	% A version of browse__browse that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
 :- pred browse__browse_synthetic(string::in, list(univ)::in, bool::in,
 	io__input_stream::in, io__output_stream::in, maybe(list(dir))::out,
 	browser_persistent_state::in, browser_persistent_state::out,
 	io__state::di, io__state::uo) is det.
 
+	% A version of browse__browse_format that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
 :- pred browse__browse_format_synthetic(string::in, list(univ)::in, bool::in,
 	io__input_stream::in, io__output_stream::in, portray_format::in,
 	browser_persistent_state::in, browser_persistent_state::out,
@@ -63,6 +69,9 @@
 :- pred browse__print(T::in, io__output_stream::in, browse_caller_type::in,
 	browser_persistent_state::in, io__state::di, io__state::uo) is det.
 
+	% A version of browse__print that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
 :- pred browse__print_synthetic(string::in, list(univ)::in, bool::in,
 	io__output_stream::in, browse_caller_type::in,
 	browser_persistent_state::in, io__state::di, io__state::uo) is det.
@@ -73,6 +82,9 @@
 	browse_caller_type::in, portray_format::in,
 	browser_persistent_state::in, io__state::di, io__state::uo) is det.
 
+	% A version of browse__print_format that works on synthetic terms
+	% in the sense of browser_info:browser_term.
+	%
 :- pred browse__print_format_synthetic(string::in, list(univ)::in, bool::in,
 	io__output_stream::in, browse_caller_type::in, portray_format::in,
 	browser_persistent_state::in, io__state::di, io__state::uo) is det.
@@ -164,13 +176,16 @@
 
 browse__print_synthetic(FunctorString, Args, IsFunc, OutputStream,
 		Caller, State) -->
-	browse__print_common(synthetic_term(FunctorString, Args, IsFunc),
-		OutputStream, Caller, no, State).
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse__print_common(BrowserTerm, OutputStream, Caller, no, State).
 
 browse__print_format_synthetic(FunctorString, Args, IsFunc, OutputStream,
 		Caller, Format, State) -->
-	browse__print_common(synthetic_term(FunctorString, Args, IsFunc),
-		OutputStream, Caller, yes(Format), State).
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse__print_common(BrowserTerm, OutputStream,
+		Caller, yes(Format), State).
 
 :- pred browse__print_common(browser_term::in, io__output_stream::in,
 	browse_caller_type::in, maybe(portray_format)::in,
@@ -212,12 +227,16 @@
 
 browse__browse_synthetic(FunctorString, Args, IsFunc,
 		InputStream, OutputStream, MaybeMark, State0, State) -->
-	browse_common(internal, synthetic_term(FunctorString, Args, IsFunc),
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse_common(internal, BrowserTerm,
 		InputStream, OutputStream, no, MaybeMark, State0, State).
 
 browse__browse_format_synthetic(FunctorString, Args, IsFunc,
 		InputStream, OutputStream, Format, State0, State) -->
-	browse_common(internal, synthetic_term(FunctorString, Args, IsFunc),
+	{ synthetic_term_to_browser_term(FunctorString, Args, IsFunc,
+		BrowserTerm) },
+	browse_common(internal, BrowserTerm,
 		InputStream, OutputStream, yes(Format), _, State0, State).
 
 browse__browse_external(Object, InputStream, OutputStream, State0, State) -->
@@ -241,6 +260,29 @@
 	{ MaybeMark = Info ^ maybe_mark },
 	{ State = Info ^ state }.
 
+% This predicate converts synthetic terms from the representation used in the
+% trace directory (as a list of arguments, the last of which represents the
+% return value for function calls) to the representation used in the browser
+% directory, in which a function call's return value is stored separately from
+% the other arguments.
+%
+% The reason why the trace directory does not use the latter representation
+% is that it would require C code to construct values of type maybe(T).
+
+:- pred synthetic_term_to_browser_term(string::in, list(univ)::in, bool::in,
+	browser_term::out) is det.
+
+synthetic_term_to_browser_term(FunctorString, Args, IsFunc, BrowserTerm) :-
+	(
+		IsFunc = no,
+		BrowserTerm = synthetic_term(FunctorString, Args, no)
+	;
+		IsFunc = yes,
+		list__split_last_det(Args, FuncArgs, Return),
+		BrowserTerm = synthetic_term(FunctorString, FuncArgs,
+			yes(Return))
+	).
+
 :- pred browse_main_loop(debugger, browser_info, browser_info, 
 		io__state, io__state).
 :- mode browse_main_loop(in, in, out, di, uo) is det.
@@ -278,7 +320,6 @@
 :- pred prompt(string::out) is det.
 prompt("browser> ").
 
-
 :- pred run_command(debugger::in, command::in, bool::out, browser_info::in,
 		browser_info::out, io__state::di, io__state::uo) is det.
 
@@ -477,20 +518,21 @@
 
 portray_flat_write_browser_term(plain_term(Univ)) -->
 	io__write_univ(Univ).
-portray_flat_write_browser_term(synthetic_term(Functor, Args, IsFunc)) -->
+portray_flat_write_browser_term(synthetic_term(Functor, Args, MaybeReturn)) -->
 	io__write_string(Functor),
-	(
-		{ IsFunc = yes },
-		{ list__split_last_det(Args, PredArgs, FuncArg) },
-		io__write_string("("),
-		io__write_list(PredArgs, ", ", io__write_univ),
-		io__write_string(") = "),
-		io__write_univ(FuncArg)
+	( { Args = [] } ->
+		[]
 	;
-		{ IsFunc = no },
 		io__write_string("("),
 		io__write_list(Args, ", ", io__write_univ),
 		io__write_string(")")
+	),
+	(
+		{ MaybeReturn = yes(Return) },
+		io__write_string(" = "),
+		io__write_univ(Return)
+	;
+		{ MaybeReturn = no }
 	).
 
 :- pred portray_verbose(debugger::in, browser_term::in, format_params::in,
@@ -532,6 +574,7 @@
 			Functor, Arity, Args)
 	->
 		string__length(Functor, FunctorSize),
+		% "()", plus Arity-1 times ", "
 		PrincipalSize = FunctorSize + Arity * 2,
 		MaxArgsSize = MaxSize - PrincipalSize,
 		list__foldl(term_size_left_from_max,
@@ -545,14 +588,16 @@
 		BrowserTerm = plain_term(Univ),
 		term_size_left_from_max(Univ, MaxSize, RemainingSize)
 	;
-		BrowserTerm = synthetic_term(Functor, Args, IsFunc),
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
 		string__length(Functor, FunctorSize),
 		list__length(Args, Arity),
 		(
-			IsFunc = yes,
-			PrincipalSize = FunctorSize + 1 + Arity * 2
+			MaybeReturn = yes(_),
+			% "()", " = ", plus Arity-1 times ", "
+			PrincipalSize = FunctorSize + Arity * 2 + 3
 		;
-			IsFunc = no,
+			MaybeReturn = no,
+			% "()", plus Arity-1 times ", "
 			PrincipalSize = FunctorSize + Arity * 2
 		),
 		MaxArgsSize = MaxSize - PrincipalSize,
@@ -586,29 +631,24 @@
 		CurSize < MaxSize,
 		CurDepth < MaxDepth,
 		limited_deconstruct_browser_term(BrowserTerm, MaxSize, Functor,
-			_Arity, Args, IsFunc)
+			_Arity, Args, MaybeReturn)
 	->
-		CurSize1 is CurSize + 1,
-		CurDepth1 is CurDepth + 1,
+		CurSize1 = CurSize + 1,
+		CurDepth1 = CurDepth + 1,
+		args_to_string_list(Args, MaxSize, CurSize1, NewSize1,
+			MaxDepth, CurDepth1, ArgStrs),
+		BracketedArgsStr = bracket_string_list(ArgStrs),
 		(
-			IsFunc = yes,
-			list__split_last_det(Args, PredArgs, FuncArg),
-			browser_term_to_string_list(PredArgs, MaxSize,
-				CurSize1, NewSize1, MaxDepth, CurDepth1,
-				PredArgStrs),
-			brack_args(PredArgStrs, BrackPredArgsStr),
-			browser_term_to_string_2(plain_term(FuncArg), MaxSize,
+			MaybeReturn = yes(Return),
+			browser_term_to_string_2(plain_term(Return), MaxSize,
 				NewSize1, NewSize, MaxDepth, CurDepth1,
-				FuncArgStr),
-			string__append_list([Functor, BrackPredArgsStr,
-				" = ", FuncArgStr], Str)
+				ReturnStr),
+			string__append_list([Functor, BracketedArgsStr,
+				" = ", ReturnStr], Str)
 		;
-			IsFunc = no,
-			browser_term_to_string_list(Args, MaxSize,
-				CurSize1, NewSize, MaxDepth, CurDepth1,
-				ArgStrs),
-		brack_args(ArgStrs, BrackArgsStr),
-		string__append_list([Functor, BrackArgsStr], Str)
+			MaybeReturn = no,
+			NewSize = NewSize1,
+			string__append_list([Functor, BracketedArgsStr], Str)
 		)
 	;
 		% Str = "...",
@@ -616,34 +656,33 @@
 		NewSize = CurSize
 	).
 
-:- pred browser_term_to_string_list(list(univ)::in, int::in, int::in, int::out,
+:- pred args_to_string_list(list(univ)::in, int::in, int::in, int::out,
 	int::in, int::in, list(string)::out) is det.
 
-browser_term_to_string_list([], _MaxSize, CurSize, NewSize,
+args_to_string_list([], _MaxSize, CurSize, NewSize,
 		_MaxDepth, _CurDepth, Strs) :-
 	Strs = [],
 	NewSize = CurSize.
-browser_term_to_string_list([Univ | Univs], MaxSize, CurSize, NewSize,
+args_to_string_list([Univ | Univs], MaxSize, CurSize, NewSize,
 		MaxDepth, CurDepth, Strs) :-
 	browser_term_to_string_2(plain_term(Univ), MaxSize, CurSize, NewSize1,
 		MaxDepth, CurDepth, Str),
-	browser_term_to_string_list(Univs, MaxSize, NewSize1, NewSize,
+	args_to_string_list(Univs, MaxSize, NewSize1, NewSize,
 		MaxDepth, CurDepth, RestStrs),
 	Strs = [Str | RestStrs].
 
-:- pred brack_args(list(string), string).
-:- mode brack_args(in, out) is det.
-brack_args(Args, Str) :-
+:- func bracket_string_list(list(string)) = string.
+
+bracket_string_list(Args) = Str :-
 	( Args = [] ->
 		Str = ""
 	;
-		comma_args(Args, CommaStr),
-		string__append_list(["(", CommaStr, ")"], Str)
+		string__append_list(["(", comma_string_list(Args), ")"], Str)
 	).
 
-:- pred comma_args(list(string), string).
-:- mode comma_args(in, out) is det.
-comma_args(Args, Str) :-
+:- func comma_string_list(list(string)) = string.
+
+comma_string_list(Args) = Str :-
 	(
 		Args = [],
 		Str = ""
@@ -652,7 +691,7 @@
 		Str = S
 	;
 		Args = [S1, S2 | Ss],
-		comma_args([S2 | Ss], Rest),
+		Rest = comma_string_list([S2 | Ss]),
 		string__append_list([S1, ", ", Rest], Str)
 	).
 
@@ -663,14 +702,13 @@
 	( Arity = 0 ->
 		Str = Functor
 	;
+		int_to_string(Arity, ArityStr),
 		(
 			IsFunc = yes,
-			int_to_string(Arity - 1, ArityS),
-			append_list([Functor, "/", ArityS, "+1"], Str)
+			append_list([Functor, "/", ArityStr, "+1"], Str)
 		;
 			IsFunc = no,
-		int_to_string(Arity, ArityS),
-		append_list([Functor, "/", ArityS], Str)
+			append_list([Functor, "/", ArityStr], Str)
 		)
 	).
 	
@@ -688,9 +726,9 @@
 	Value = univ_value(Univ),
 	Doc = to_doc(MaxDepth, Value),
 	Str = to_string(Width, Doc).
-browser_term_to_string_raw_pretty(synthetic_term(Functor, Args, IsFunc), Width,
-		MaxDepth, Str) :-
-	Doc = synthetic_term_to_doc(MaxDepth, Functor, Args, IsFunc),
+browser_term_to_string_raw_pretty(synthetic_term(Functor, Args, MaybeReturn),
+		Width, MaxDepth, Str) :-
+	Doc = synthetic_term_to_doc(MaxDepth, Functor, Args, MaybeReturn),
 	Str = to_string(Width, Doc).
 
 %---------------------------------------------------------------------------%
@@ -719,14 +757,21 @@
 		CurSize < MaxSize,
 		CurDepth < MaxDepth,
 		limited_deconstruct_browser_term(BrowserTerm, MaxSize, Functor,
-			_Arity, Args, _IsFunc)
+			_Arity, Args0, MaybeReturn)
 	->
+		% XXX we should consider formatting function terms differently.
+		(
+			MaybeReturn = yes(Return),
+			list__append(Args0, [Return], Args)
+		;
+			MaybeReturn = no,
+			Args = Args0
+		),
 		CurSize1 is CurSize + 1,
 		CurDepth1 is CurDepth + 1,
 		ArgNum = 1,
-		browser_term_to_string_verbose_list(Args, ArgNum,
-			MaxSize, CurSize1, NewSize,
-			MaxDepth, CurDepth1, ArgsFrame),
+		args_to_string_verbose_list(Args, ArgNum, MaxSize, CurSize1,
+			NewSize, MaxDepth, CurDepth1, ArgsFrame),
 		frame__vglue([Functor], ArgsFrame, Frame)
 	;
 		browser_term_compress(BrowserTerm, Line),
@@ -734,13 +779,13 @@
 		NewSize = CurSize
 	).
 
-:- pred browser_term_to_string_verbose_list(list(univ)::in, int::in, int::in,
+:- pred args_to_string_verbose_list(list(univ)::in, int::in, int::in,
 	int::in, int::out, int::in, int::in, frame::out) is det.
 
-browser_term_to_string_verbose_list([], _ArgNum, _MaxSize, CurSize, NewSize,
+args_to_string_verbose_list([], _ArgNum, _MaxSize, CurSize, NewSize,
 		_MaxDepth, _CurDepth, []) :-
 	NewSize = CurSize.
-browser_term_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
+args_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
 		MaxDepth, CurDepth, Frame) :-
 	browser_term_to_string_verbose_2(plain_term(Univ), MaxSize,
 		CurSize, NewSize, MaxDepth, CurDepth, TreeFrame),
@@ -748,12 +793,12 @@
 	string__int_to_string(ArgNum, ArgNumS),
 	string__append_list([ArgNumS, "-"], LastBranchS),
 	frame__hglue([LastBranchS], TreeFrame, Frame).
-browser_term_to_string_verbose_list([Univ1, Univ2 | Univs], ArgNum, MaxSize,
+args_to_string_verbose_list([Univ1, Univ2 | Univs], ArgNum, MaxSize,
 		CurSize, NewSize, MaxDepth, CurDepth, Frame) :-
 	browser_term_to_string_verbose_2(plain_term(Univ1), MaxSize, CurSize,
 		NewSize1, MaxDepth, CurDepth, TreeFrame),
 	ArgNum1 is ArgNum + 1,
-	browser_term_to_string_verbose_list([Univ2 | Univs], ArgNum1, MaxSize,
+	args_to_string_verbose_list([Univ2 | Univs], ArgNum1, MaxSize,
 		NewSize1, NewSize2, MaxDepth, CurDepth, RestTreesFrame),
 	NewSize = NewSize2,
 	% XXX: ArgNumS must have fixed length 2.
@@ -846,25 +891,36 @@
 		deref_subterm_2(Univ, SimplifiedPath, SubUniv),
 		SubBrowserTerm = plain_term(SubUniv)
 	;
-		BrowserTerm = synthetic_term(_FunctorString, Args, _IsFunc),
+		BrowserTerm = synthetic_term(_Functor, Args, MaybeReturn),
 		(
-			Path = [],
+			SimplifiedPath = [],
 			SubBrowserTerm = BrowserTerm
 		;
-			Path = [Dir | _Dirs],
+			SimplifiedPath = [Step | SimplifiedPathTail],
 			(
-				Dir = child_num(N),
+				Step = child_num(N),
 				% The first argument of a non-array is numbered
 				% argument 1.
-				list__index1(Args, N, SubUniv),
-				SubBrowserTerm = plain_term(SubUniv)
+				list__index1(Args, N, ArgUniv)
 			;
-				Dir = child_name(_),
-				fail
+				Step = child_name(Name),
+				(
+					MaybeReturn = yes(ArgUnivPrime),
+					( Name = "r"
+					; Name = "res"
+					; Name = "result"
+					)
+				->
+					ArgUniv = ArgUnivPrime
+				;
+					fail
+				)
 			;
-				Dir = parent,
+				Step = parent,
 				error("deref_subterm: found parent")
-			)
+			),
+			deref_subterm_2(ArgUniv, SimplifiedPathTail, SubUniv),
+			SubBrowserTerm = plain_term(SubUniv)
 		)
 	).
 
@@ -1117,5 +1173,61 @@
 	write(Term),
 	print(".\n"),
 	flush_output.
+
+%---------------------------------------------------------------------------%
+
+    % These two functions are just like like pprint:to_doc, except their input
+    % is not a natural term, but a synthetic term defined by a functor, a list
+    % of arguments, and a boolean that is true iff the synthetic term is a
+    % function application, and thus should be printed not as f(a1, ... an)
+    % but as f(a1, ... an-1) = an.
+:- func synthetic_term_to_doc(string, list(univ), maybe(univ))      = doc.
+:- func synthetic_term_to_doc(int, string, list(univ), maybe(univ)) = doc.
+
+synthetic_term_to_doc(Functor, Args, MaybeReturn) =
+	synthetic_term_to_doc(int__max_int, Functor, Args, MaybeReturn).
+
+synthetic_term_to_doc(Depth, Functor, Args, MaybeReturn) = Doc :-
+	Arity = list__length(Args),
+	( Depth =< 0 ->
+		( Arity = 0 ->
+			Doc = text(Functor)
+		;
+			(
+				MaybeReturn = yes(_),
+				Doc = text(Functor) `<>` text("/") `<>`
+					poly(i(Arity)) `<>` text("+1") 
+			;
+				MaybeReturn = no,
+				Doc = text(Functor) `<>` text("/") `<>`
+					poly(i(Arity))
+			)
+		)
+	;
+		( Arity = 0 ->
+			Doc = text(Functor)
+		;
+			ArgDocs = packed_cs_univ_args(Depth - 1, Args),
+			(
+				MaybeReturn = yes(Return),
+				Doc = group(
+					text(Functor) `<>`
+					parentheses(
+						nest(2, ArgDocs)
+					) `<>`
+					nest(2, text(" = ") `<>`
+						to_doc(Depth - 1, Return)
+					)
+				)
+			;
+				MaybeReturn = no,
+				Doc = group(
+					text(Functor) `<>` parentheses(
+						nest(2, ArgDocs)
+					)
+				)
+			)
+		)
+	).
 
 %---------------------------------------------------------------------------%
diff -u browser/browser_info.m browser/browser_info.m
--- browser/browser_info.m
+++ browser/browser_info.m
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 2000-2001 The University of Melbourne.
+% Copyright (C) 2000-2002 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.
 %---------------------------------------------------------------------------%
@@ -24,8 +24,10 @@
 					% such as a predicate name applied to
 					% a list of arguments. The string says
 					% what we should print as the functor.
-			list(univ),
-			bool
+			list(univ),	% The arguments.
+			maybe(univ)	% If yes, the synthetic term represents
+					% a function call, and the argument
+					% inside the yes() is the return value.
 		).
 
 	% The non-persistent browser information.  A new one of these is
@@ -138,11 +140,18 @@
 
 %---------------------------------------------------------------------------%
 
+% These three predicates are like the deconstruct, limited_deconstruct and
+% functor procedures in std_util, except they work on browser_terms.
+% This requires them to have an extra argument (the last). For deconstruct
+% and limited_deconstruct, this returns the return value if the browser term
+% represents a function call. For functor, it says whether the browser term
+% represents a function call.
+
 :- pred deconstruct_browser_term(browser_term::in,
-	string::out, int::out, list(univ)::out, bool::out) is det.
+	string::out, int::out, list(univ)::out, maybe(univ)::out) is det.
 
 :- pred limited_deconstruct_browser_term(browser_term::in, int::in,
-	string::out, int::out, list(univ)::out, bool::out) is semidet.
+	string::out, int::out, list(univ)::out, maybe(univ)::out) is semidet.
 
 :- pred functor_browser_term(browser_term::in, string::out, int::out,
 	bool::out) is det.
@@ -439,25 +448,25 @@
 
 %---------------------------------------------------------------------------%
 
-deconstruct_browser_term(BrowserTerm, Functor, Arity, Args, IsFunc) :-
+deconstruct_browser_term(BrowserTerm, Functor, Arity, Args, MaybeReturn) :-
 	(
 		BrowserTerm = plain_term(Univ),
 		deconstruct(univ_value(Univ), Functor, Arity, Args),
-		IsFunc = no
+		MaybeReturn = no
 	;
-		BrowserTerm = synthetic_term(Functor, Args, IsFunc),
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
 		list__length(Args, Arity)
 	).
 
 limited_deconstruct_browser_term(BrowserTerm, Limit, Functor, Arity, Args,
-		IsFunc) :-
+		MaybeReturn) :-
 	(
 		BrowserTerm = plain_term(Univ),
 		limited_deconstruct(univ_value(Univ), Limit,
 			Functor, Arity, Args),
-		IsFunc = no
+		MaybeReturn = no
 	;
-		BrowserTerm = synthetic_term(Functor, Args, IsFunc),
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
 		list__length(Args, Arity)
 	).
 
@@ -467,8 +476,15 @@
 		functor(univ_value(Univ), Functor, Arity),
 		IsFunc = no
 	;
-		BrowserTerm = synthetic_term(Functor, Args, IsFunc),
-		list__length(Args, Arity)
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
+		list__length(Args, Arity),
+		(
+			MaybeReturn = yes(_),
+			IsFunc = yes
+		;
+			MaybeReturn = no,
+			IsFunc = no
+		)
 	).
 
 %---------------------------------------------------------------------------%
diff -u browser/sized_pretty.m browser/sized_pretty.m
--- browser/sized_pretty.m
+++ browser/sized_pretty.m
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 2001 The University of Melbourne.
+% Copyright (C) 2001-2002 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.
 %---------------------------------------------------------------------------%
@@ -164,12 +164,15 @@
 :- import_module mdb__browser_info.
 :- import_module std_util, int, string.
 
-	% This may throw an exception or cause a runtime abort if the term
-	% in question has user-defined equality. 
-	% The Limit is number of lines.
+	% sized_pretty__univ_to_string_line(Univ, LineWidth, Lines, String)
+	% Converts the term in Univ to a string that fits into Lines lines
+	% of width LineWidth. It may throw an exception or cause a runtime
+	% abort if the term in question has no canonical representation.
 :- pred sized_pretty__univ_to_string_line(univ::in, int::in, int::in,
 	string::out) is det.
 
+	% The same as sized_pretty__univ_to_string_line, except works on
+	% browser_terms.
 :- pred sized_pretty__browser_term_to_string_line(browser_term::in,
 	int::in, int::in, string::out) is det.
 
@@ -259,6 +262,7 @@
 	% Head Term is going to be printed on a single line then it should be
 	% given a limit of character_count(LineWidth - 1) instead of
 	% character_count(LineWidth - 3).
+
 sized_pretty__univ_to_string_line(Univ, LineWidth, Lines, String) :-
 	sized_pretty__browser_term_to_string_line(plain_term(Univ),
 		LineWidth, Lines, String).
@@ -266,7 +270,7 @@
 sized_pretty__browser_term_to_string_line(BrowserTerm, LineWidth, Lines,
 		String) :-
 	Params = measure_params(LineWidth),
-	functor_browser_term(BrowserTerm, _Functor, Arity, _IsFunc),
+	functor_browser_term(BrowserTerm, _Functor, Arity, _MaybeReturn),
 	(
 		Arity \= 0,
 		Lines \= 0,
@@ -307,7 +311,7 @@
 	MaxFunctors = maximum_functors(Limit, Params),
 	(
 		limited_deconstruct_browser_term(BrowserTerm, MaxFunctors,
-			Functor, Arity, Args, _IsFunc)
+			Functor, Arity, Args, _MaybeReturn)
 	->
 		measured_split(BrowserTerm, Params, Limit, Arity, yes,
 			FunctorSize, MaybeInitArgLimit, NewLimit, NewParams),
@@ -557,14 +561,14 @@
 	functor(univ_value(Univ), Functor, Arity),
 		Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity))
 	;
-		BrowserTerm = synthetic_term(Functor, Args, IsFunc),
+		BrowserTerm = synthetic_term(Functor, Args, MaybeReturn),
 		list__length(Args, Arity),
 		(
-			IsFunc = yes,
+			MaybeReturn = yes(_),
 			Doc = text(Functor) `<>` text("/") `<>`
-				poly(i(Arity - 1)) `<>` text("+1")
+				poly(i(Arity)) `<>` text("+1")
 		;
-			IsFunc = no,
+			MaybeReturn = no,
 			Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity))
 		)
 	).
@@ -648,7 +652,7 @@
 	( Arity = 0 ->
 		MaybeArgLimit = no
 	;
-		( Limit =< (Arity + 1) ->			
+		( Limit =< Arity + 1 ->			
 			MaybeArgLimit = no
 		;
 			RoundUp = (Limit + Arity - 1) // Arity,
@@ -715,20 +719,20 @@
 char_count_split(BrowserTerm, Params, char_count(Limit), Arity, Check, 
 		char_count(FunctorSize), MaybeArgLimit, char_count(Limit),
 		Params) :-
-	deconstruct_browser_term(BrowserTerm, Functor, _, Args, IsFunc),
+	deconstruct_browser_term(BrowserTerm, Functor, _, Args, MaybeReturn),
 	( Check = yes ->
 		get_arg_length(Args, TotalLength, _)
 	;
 		TotalLength = 0
 	),
 	(
-		IsFunc = yes,
-		% Arity-2 times the string ", ", once "()", and once " = "
-		FunctorSize = string__length(Functor) + 1 + 2 * (Arity)
+		MaybeReturn = yes(_),
+		% Arity-1 times the string ", ", once "()", and once " = "
+		FunctorSize = string__length(Functor) + 2 * Arity + 3
 	;
-		IsFunc = no,
+		MaybeReturn = no,
 		% Arity-1 times the string ", ", and once "()"
-		FunctorSize = string__length(Functor) + 2 * (Arity)
+		FunctorSize = string__length(Functor) + 2 * Arity
 	),
 	( Arity = 0 ->
 		MaybeArgLimit = no
@@ -887,7 +891,7 @@
 	% LineWidth is length of the line in which the functor is printed.
 	Params = measure_params(LineWidth),
 	deconstruct_browser_term(BrowserTerm, Functor, ActualArity, Args,
-		IsFunc),
+		MaybeReturn),
     	FSize = string__length(Functor) + 2 * (ActualArity),
     	( Check = yes ->
     		get_arg_length(Args, TotalLength, MaxArgLength),
@@ -948,19 +952,16 @@
 			% If an ordinary term is not deconstructed, it is
 			% printed as "functor/Arity". If a synthetic function
 			% term is not deconstructed, it is printed as
-			% "functor/n+1", where n is Arity-1.
-			% XXX we should
+			% "functor/Arity+1".
 			(
-				IsFunc = no,
-				FuncSuffixChars = 0,
-				EffArity = Arity
+				MaybeReturn = yes(_),
+				FuncSuffixChars = 2
 			;
-				IsFunc = yes,
-				FuncSuffixChars = 2,
-				EffArity = Arity - 1
+				MaybeReturn = no,
+				FuncSuffixChars = 0
 			),
 			FunctorLength = string__length(Functor),
-			string__int_to_string(EffArity, ArityStr),
+			string__int_to_string(Arity, ArityStr),
 			string__length(ArityStr, ArityChars),
 			FunctorSize = character_count(FunctorLength + 1
 				+ ArityChars + FuncSuffixChars),
diff -u browser/util.m browser/util.m
--- browser/util.m
+++ browser/util.m
@@ -74,7 +74,7 @@
 :- pred util__limit(pred(list(T), list(T)), list(T), list(T)).
 :- mode util__limit(pred(in,out) is det, in, out) is det.
 
-	% For use in representing unbound head variables in the "print atom"
+	% For use in representing unbound head variables in the "print goal"
 	% commands in the debugger.
 :- type unbound ---> '_'.
 
diff -u library/pprint.m library/pprint.m
--- library/pprint.m
+++ library/pprint.m
@@ -150,7 +150,7 @@
 
 :- interface.
 
-:- import_module std_util, bool, int, string, list, io.
+:- import_module std_util, int, string, list, io.
 
     % Clients must translate data structures into docs for
     % the pretty printer to display.
@@ -250,6 +250,16 @@
     %
 :- func packed_cs(int, list(doc)) = doc.
 
+    % This is like a depth-limited version of packed_cs/1 that first
+    % calls to_doc/2 on each member of the argument list.
+    %
+:- func packed_cs_to_depth(int, list(T)) = doc.
+
+    % This is like a version of packed_cs_to_depth/1 that first
+    % calls univ_value/1 for each member of the argument list.
+    %
+:- func packed_cs_univ_args(int, list(univ)) = doc.
+
     % separated(PP, Sep, [X1,...,Xn]) =
     %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
     %
@@ -293,14 +303,6 @@
 :- func to_doc(T)           = doc.
 :- func to_doc(int, T)      = doc.
 
-    % These two functions are just like like to_doc, except their input is not
-    % a natural term, but a synthetic term defined by a functor, a list of
-    % arguments, and a boolean that is true iff the synthetic term is a
-    % function application, and thus should be printed not as f(a1, ... an)
-    % but as f(a1, ... an-1) = an.
-:- func synthetic_term_to_doc(string, list(univ), bool)           = doc.
-:- func synthetic_term_to_doc(int, string, list(univ), bool)      = doc.
-
     % Convert docs to pretty printed strings.  The int
     % argument specifies a line width in characters.
     %
@@ -320,7 +322,7 @@
 
 :- implementation.
 
-:- import_module char, array, map, require.
+:- import_module char, array, map.
 
 :- type doc
     --->    'NIL'
@@ -534,21 +536,11 @@
 
 %------------------------------------------------------------------------------%
 
-    % This is like a depth-limited version of packed_cs/1 that first
-    % calls to_doc/2 on each member of the argument list.
-    %
-:- func packed_cs_to_depth(int, list(T)) = doc.
-
 packed_cs_to_depth(Depth, Xs) =
     packed_cs(Depth, list__map(to_doc(Depth), Xs)).
 
 %------------------------------------------------------------------------------%
 
-    % This is like a version of packed_cs_to_depth/1 that first
-    % calls univ_value/1 for each member of the argument list.
-    %
-:- func packed_cs_univ_args(int, list(univ)) = doc.
-
 packed_cs_univ_args(Depth, UnivArgs) = 
     packed_cs(
 
@@ -576,8 +568,6 @@
 %------------------------------------------------------------------------------%
 
 to_doc(X) = to_doc(int__max_int, X).
-synthetic_term_to_doc(Functor, Args, IsFunc) =
-    synthetic_term_to_doc(int__max_int, Functor, Args, IsFunc).
 
 %------------------------------------------------------------------------------%
 
@@ -607,53 +597,6 @@
       else    generic_term_to_doc(Depth, X)
     ).
 
-synthetic_term_to_doc(Depth, Functor, Args, IsFunc) = Doc :-
-    list__length(Args, Arity),
-    ( Depth =< 0 ->
-        ( Arity = 0 ->
-            Doc = text(Functor)
-        ;
-            IsFunc = yes,
-            Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity - 1))
-                `<>` text("+1") 
-        ;
-            IsFunc = no,
-            Doc = text(Functor) `<>` text("/") `<>` poly(i(Arity))
-        )
-    ;
-        ( Arity = 0 ->
-            Doc = text(Functor)
-        ;
-            (
-                IsFunc = yes,
-                list__length(Args, NumArgs),
-                (
-                    list__split_list(NumArgs - 1, Args, PredArgsPrime,
-                        FuncArgs),
-                    FuncArgs = [FuncArgPrime]
-                ->
-                    PredArgs = PredArgsPrime,
-                    FuncArg = FuncArgPrime
-                ;
-                    error("synthetic_term_to_doc: length mismatch")
-                ),
-                Doc = group(
-                        text(Functor) `<>` parentheses(
-                            nest(2, packed_cs_univ_args(Depth - 1, PredArgs))
-                        ) `<>`
-                        nest(2, text(" = ") `<>` to_doc(Depth - 1, FuncArg))
-                    )
-            ;
-                IsFunc = no,
-                Doc = group(
-                        text(Functor) `<>` parentheses(
-                            nest(2, packed_cs_univ_args(Depth - 1, Args))
-                        )
-                    )
-            )
-        )
-    ).
-
 %------------------------------------------------------------------------------%
 
 :- some [T2] pred dynamic_cast_to_array(T1, array(T2)).
@@ -753,7 +696,7 @@
 
 out_of_depth_term_to_doc(X) = Doc :-
 
-    functor(X, Name, Arity),
+    deconstruct(X, Name, Arity, _UnivArgs),
 
     Doc = ( if Arity = 0 then text(Name)
                          else text(Name) `<>` text("/") `<>` poly(i(Arity))
diff -u runtime/mercury_type_info.h runtime/mercury_type_info.h
--- runtime/mercury_type_info.h
+++ runtime/mercury_type_info.h
@@ -308,7 +308,7 @@
 		(MR_TypeInfo)     (ti1)					\
 	};
 
-#define MR_static_type_info_arity_2(name, ctor, ti1, t2)		\
+#define MR_static_type_info_arity_2(name, ctor, ti1, ti2)		\
 	struct {							\
 		MR_TypeCtorInfo field1;					\
 		MR_TypeInfo 	field2;					\
@@ -326,7 +326,7 @@
 
 #ifdef MR_HIGHLEVEL_CODE
 
-#define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
+  #define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
 		MR_type_ctor_info_name(builtin, TYPE, ARITY)
 
   #define MR_type_ctor_info_name(MODULE, TYPE, ARITY)			      \
@@ -376,6 +376,23 @@
 		-1							      \
 	}
 
+#else /* MR_HIGHLEVEL_CODE */
+
+  #define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
+	MR_PASTE2(mercury_data_,					      \
+	MR_PASTE2(__type_ctor_info_,					      \
+	MR_PASTE2(TYPE,							      \
+	MR_PASTE2(_,							      \
+		 ARITY))))
+
+  #define MR_type_ctor_info_name(MODULE, TYPE, ARITY)			      \
+	MR_PASTE2(mercury_data_,					      \
+	MR_PASTE2(MODULE,						      \
+	MR_PASTE2(__type_ctor_info_,					      \
+	MR_PASTE2(TYPE,							      \
+	MR_PASTE2(_,							      \
+		 ARITY)))))
+
 #endif /* MR_HIGHLEVEL_CODE */
 
 /*---------------------------------------------------------------------------*/
@@ -392,15 +409,25 @@
 	** the same primary tag (1), and are all allocated secondary tags
 	** starting from 0.
 	*/
-    #define MR_COMPARE_TAG      MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
+  #define MR_ENUM_TAG         MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
  
-    #define MR_COMPARE_EQUAL    MR_mkword(MR_COMPARE_TAG, MR_mkbody(0))
-    #define MR_COMPARE_LESS     MR_mkword(MR_COMPARE_TAG, MR_mkbody(1))
-    #define MR_COMPARE_GREATER  MR_mkword(MR_COMPARE_TAG, MR_mkbody(2))         
+  #define MR_COMPARE_EQUAL    MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
+  #define MR_COMPARE_LESS     MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
+  #define MR_COMPARE_GREATER  MR_mkword(MR_ENUM_TAG, MR_mkbody(2))         
+
+  #define MR_BOOL_NO          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
+  #define MR_BOOL_YES         MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
+
+  #define MR_UNBOUND          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
 #else
     #define MR_COMPARE_EQUAL    0
     #define MR_COMPARE_LESS     1
     #define MR_COMPARE_GREATER  2
+
+  #define MR_BOOL_NO          0
+  #define MR_BOOL_YES         1
+
+  #define MR_UNBOUND          0
 #endif
 
 /*---------------------------------------------------------------------------*/
@@ -414,23 +441,6 @@
 
   #endif /* MR_BOOTSTRAP_TYPE_CTOR_VERSION_NO */
 
-#else /* MR_HIGHLEVEL_CODE */
-
-  #define MR_builtin_type_ctor_info_name(TYPE, ARITY)			      \
-	MR_PASTE2(mercury_data_,					      \
-	MR_PASTE2(__type_ctor_info_,					      \
-	MR_PASTE2(TYPE,							      \
-	MR_PASTE2(_,							      \
-		 ARITY))))
-
-  #define MR_type_ctor_info_name(MODULE, TYPE, ARITY)			      \
-	MR_PASTE2(mercury_data_,					      \
-	MR_PASTE2(MODULE,						      \
-	MR_PASTE2(__type_ctor_info_,					      \
-	MR_PASTE2(TYPE,							      \
-	MR_PASTE2(_,							      \
-		 ARITY)))))
-
 #endif /* MR_HIGHLEVEL_CODE */
 
 /*---------------------------------------------------------------------------*/
@@ -447,25 +457,15 @@
 	** the same primary tag (1), and are all allocated secondary tags
 	** starting from 0.
 	*/
-  #define MR_ENUM_TAG         MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
+    #define MR_COMPARE_TAG      MR_mktag(MR_FIRST_UNRESERVED_RAW_TAG)
  
-  #define MR_COMPARE_EQUAL    MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
-  #define MR_COMPARE_LESS     MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
-  #define MR_COMPARE_GREATER  MR_mkword(MR_ENUM_TAG, MR_mkbody(2))         
-
-  #define MR_BOOL_NO          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
-  #define MR_BOOL_YES         MR_mkword(MR_ENUM_TAG, MR_mkbody(1))
-
-  #define MR_UNBOUND          MR_mkword(MR_ENUM_TAG, MR_mkbody(0))
+    #define MR_COMPARE_EQUAL    MR_mkword(MR_COMPARE_TAG, MR_mkbody(0))
+    #define MR_COMPARE_LESS     MR_mkword(MR_COMPARE_TAG, MR_mkbody(1))
+    #define MR_COMPARE_GREATER  MR_mkword(MR_COMPARE_TAG, MR_mkbody(2))         
 #else
     #define MR_COMPARE_EQUAL    0
     #define MR_COMPARE_LESS     1
     #define MR_COMPARE_GREATER  2
-
-  #define MR_BOOL_NO          0
-  #define MR_BOOL_YES         1
-
-  #define MR_UNBOUND          0
 #endif
 
 /*---------------------------------------------------------------------------*/
diff -u tests/debugger/browse_pretty.exp tests/debugger/browse_pretty.exp
--- tests/debugger/browse_pretty.exp
+++ tests/debugger/browse_pretty.exp
@@ -104,10 +104,10 @@
   [|](1, [|](2, [|]/2)), 
   small)
 browser> quit
-mdb> print atom
+mdb> print goal
 big_data(
   big(big/3, [|]/2, big/3))
-mdb> browse atom
+mdb> browse goal
 browser> ls
 big_data(
   big(big/3, [|]/2, big/3))
@@ -121,6 +121,9 @@
 browser> ls
 big_data(
   big(big/3, [|]/2, big/3))
+browser> ^1^2^2
+browser> ls
+[|](2, [|](3, []))
 browser> quit
 mdb> continue
 big(big(big(small, [1], small), [1, 2], small), [1, 2, 3], big(big(small, [1, 2, 3, 4], big(small, [1, 2, 3, 4, 5], small)), [1, 2, 3, 4, 5, 6], small)).
diff -u tests/debugger/browse_pretty.inp tests/debugger/browse_pretty.inp
--- tests/debugger/browse_pretty.inp
+++ tests/debugger/browse_pretty.inp
@@ -28,13 +28,14 @@
 set width 30
 ls
 quit
-print atom
-browse atom
+print goal
+browse goal
 ls
 ^1
 ls
 ^..
 ls
+^1^2^2
+ls
 quit
 continue
-
diff -u tests/debugger/polymorphic_output.exp tests/debugger/polymorphic_output.exp
--- tests/debugger/polymorphic_output.exp
+++ tests/debugger/polymorphic_output.exp
@@ -10,11 +10,11 @@
        2:      2  2 CALL func polymorphic_output:functor_names/2-0 (det)
 mdb> delete 0
  0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
-mdb> p atom
+mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
 mdb> set format verbose
 mdb> set lines 100
-mdb> p atom
+mdb> p goal
 functor_names
 1-two
 | 1-"three"
@@ -35,6 +35,22 @@
 2-_
 
 mdb> set format flat
+mdb> browse goal
+browser> ^1
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^2
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^3
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))
+browser> ^..^r
+browser> p
+'_'
+browser> quit
 mdb> b std_util__det_arg
 mdb: there is no such procedure.
 mdb> c
diff -u tests/debugger/polymorphic_output.exp2 tests/debugger/polymorphic_output.exp2
--- tests/debugger/polymorphic_output.exp2
+++ tests/debugger/polymorphic_output.exp2
@@ -10,11 +10,11 @@
        4:      3  2 CALL func polymorphic_output:functor_names/2-0 (det)
 mdb> delete 0
  0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
-mdb> p atom
+mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
 mdb> set format verbose
 mdb> set lines 100
-mdb> p atom
+mdb> p goal
 functor_names
 1-two
 | 1-"three"
diff -u tests/debugger/polymorphic_output.exp3 tests/debugger/polymorphic_output.exp3
--- tests/debugger/polymorphic_output.exp3
+++ tests/debugger/polymorphic_output.exp3
@@ -10,11 +10,11 @@
        2:      2  2 CALL func polymorphic_output:functor_names/2-0 (det)
 mdb> delete 0
  0: E stop  interface func polymorphic_output:functor_names/2-0 (det)
-mdb> p atom
+mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
 mdb> set format verbose
 mdb> set lines 100
-mdb> p atom
+mdb> p goal
 functor_names
 1-two
 | 1-"three"
@@ -35,6 +35,22 @@
 2-_
 
 mdb> set format flat
+mdb> browse goal
+browser> ^1
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^2
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^3
+error: cannot change to subterm
+browser> p
+two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two/4)
+browser> ^..^r
+browser> p
+'_'
+browser> quit
 mdb> b std_util__det_arg
 mdb: there is no such procedure.
 mdb> c
diff -u tests/debugger/polymorphic_output.inp tests/debugger/polymorphic_output.inp
--- tests/debugger/polymorphic_output.inp
+++ tests/debugger/polymorphic_output.inp
@@ -4,11 +4,21 @@
 b functor_names
 c
 delete 0
-p atom
+p goal
 set format verbose
 set lines 100
-p atom
+p goal
 set format flat
+browse goal
+^1
+p
+^..^2
+p
+^..^3
+p
+^..^r
+p
+quit
 b std_util__det_arg
 c
 P
diff -u trace/mercury_trace_browse.c trace/mercury_trace_browse.c
--- trace/mercury_trace_browse.c
+++ trace/mercury_trace_browse.c
@@ -87,7 +87,7 @@
 }
 
 void
-MR_trace_browse_atom(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
+MR_trace_browse_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
 	MR_Browse_Format format)
 {
 	MercuryFile	mdb_in, mdb_out;
@@ -177,7 +177,7 @@
 }
 
 void
-MR_trace_print_atom(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
+MR_trace_print_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
 	MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
 	MercuryFile mdb_out;
diff -u trace/mercury_trace_browse.h trace/mercury_trace_browse.h
--- trace/mercury_trace_browse.h
+++ trace/mercury_trace_browse.h
@@ -46,7 +46,7 @@
 */
 extern 	void	MR_trace_browse(MR_Word type_info, MR_Word value,
 			MR_Browse_Format format);
-extern 	void	MR_trace_browse_atom(MR_ConstString name, MR_Word arg_list,
+extern 	void	MR_trace_browse_goal(MR_ConstString name, MR_Word arg_list,
 			MR_Word is_func, MR_Browse_Format format);
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 extern 	void	MR_trace_browse_external(MR_Word type_info, MR_Word value,
@@ -54,11 +54,11 @@
 #endif
 
 /*
-** Display a term (non-interactively).
+** Display a term non-interactively.
 */
 extern	void	MR_trace_print(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
-extern	void	MR_trace_print_atom(MR_ConstString name, MR_Word arg_list,
+extern	void	MR_trace_print_goal(MR_ConstString name, MR_Word arg_list,
 			MR_Word is_func, MR_Browse_Caller_Type caller,
 			MR_Browse_Format format);
 
diff -u trace/mercury_trace_internal.c trace/mercury_trace_internal.c
--- trace/mercury_trace_internal.c
+++ trace/mercury_trace_internal.c
@@ -226,7 +226,7 @@
 			bool detailed);
 static	void	MR_trace_browse_internal(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
-static	void	MR_trace_browse_atom_internal(MR_ConstString name,
+static	void	MR_trace_browse_goal_internal(MR_ConstString name,
 			MR_Word arg_list, MR_Word is_func,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 static	const char *MR_trace_browse_exception(MR_Event_Info *event_info,
@@ -504,26 +504,26 @@
 }
 
 static void
-MR_trace_browse_atom_internal(MR_ConstString name, MR_Word arg_list,
+MR_trace_browse_goal_internal(MR_ConstString name, MR_Word arg_list,
 	MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
 	switch (caller) {
 		
 		case MR_BROWSE_CALLER_BROWSE:
-			MR_trace_browse_atom(name, arg_list, is_func, format);
+			MR_trace_browse_goal(name, arg_list, is_func, format);
 			break;
 
 		case MR_BROWSE_CALLER_PRINT:
-			MR_trace_print_atom(name, arg_list, is_func,
+			MR_trace_print_goal(name, arg_list, is_func,
 				caller, format);
 			break;
 
 		case MR_BROWSE_CALLER_PRINT_ALL:
-			MR_fatal_error("MR_trace_browse_atom_internal:"
+			MR_fatal_error("MR_trace_browse_goal_internal:"
 				" bad caller type");
 
 		default:
-			MR_fatal_error("MR_trace_browse_atom_internal:"
+			MR_fatal_error("MR_trace_browse_goal_internal:"
 				" unknown caller type");
 	}
 }
@@ -1070,20 +1070,31 @@
 					"browsing", "print"))
 		{
 			; /* the usage message has already been printed */
+		} else if (word_count == 1) {
+			const char	*problem;
+
+			problem = MR_trace_browse_one_goal(MR_mdb_out,
+				MR_trace_browse_goal_internal,
+				MR_BROWSE_CALLER_PRINT, format);
+
+			if (problem != NULL) {
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+			}
 		} else if (word_count == 2) {
 			const char	*problem;
 
 			if (streq(words[1], "*")) {
 				problem = MR_trace_browse_all(MR_mdb_out,
 					MR_trace_browse_internal, format);
+			} else if (streq(words[1], "goal")) {
+				problem = MR_trace_browse_one_goal(MR_mdb_out,
+					MR_trace_browse_goal_internal,
+					MR_BROWSE_CALLER_PRINT, format);
 			} else if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
 					MR_trace_browse_internal,
 					MR_BROWSE_CALLER_PRINT, format);
-			} else if (streq(words[1], "atom")) {
-				problem = MR_trace_browse_one_atom(MR_mdb_out,
-					MR_trace_browse_atom_internal,
-					MR_BROWSE_CALLER_PRINT, format);
 			} else {
 				problem = MR_trace_parse_browse_one(MR_mdb_out,
 					words[1], MR_trace_browse_internal,
@@ -1104,12 +1115,23 @@
 					"browsing", "browse"))
 		{
 			; /* the usage message has already been printed */
+		} else if (word_count == 1) {
+			const char	*problem;
+
+			problem = MR_trace_browse_one_goal(MR_mdb_out,
+				MR_trace_browse_goal_internal,
+				MR_BROWSE_CALLER_BROWSE, format);
+
+			if (problem != NULL) {
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+			}
 		} else if (word_count == 2) {
 			const char	*problem;
 
-			if (streq(words[1], "atom")) {
-				problem = MR_trace_browse_one_atom(MR_mdb_out,
-					MR_trace_browse_atom_internal,
+			if (streq(words[1], "goal")) {
+				problem = MR_trace_browse_one_goal(MR_mdb_out,
+					MR_trace_browse_goal_internal,
 					MR_BROWSE_CALLER_BROWSE, format);
 			} else if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
diff -u trace/mercury_trace_vars.c trace/mercury_trace_vars.c
--- trace/mercury_trace_vars.c
+++ trace/mercury_trace_vars.c
@@ -668,7 +668,7 @@
 	&MR_type_ctor_info_name(mdb__util, unbound, 0));
 
 const char *
-MR_trace_browse_one_atom(FILE *out, MR_AtomBrowser browser,
+MR_trace_browse_one_goal(FILE *out, MR_GoalBrowser browser,
 	MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
 	const MR_Proc_Layout	*proc_layout;
diff -u trace/mercury_trace_vars.h trace/mercury_trace_vars.h
--- trace/mercury_trace_vars.h
+++ trace/mercury_trace_vars.h
@@ -46,7 +46,7 @@
 typedef	void	(*MR_Browser)(MR_Word type_info, MR_Word value,
 			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 
-typedef	void	(*MR_AtomBrowser)(MR_ConstString atom_name, MR_Word arg_list,
+typedef	void	(*MR_GoalBrowser)(MR_ConstString name, MR_Word arg_list,
 			MR_Word is_func, MR_Browse_Caller_Type caller,
 			MR_Browse_Format format);
 
@@ -108,14 +108,14 @@
 extern	const char	*MR_trace_headvar_num(int n, int *num);
 
 /*
-** Print the call of the current level as an atom.
+** Print the call of the current level as a goal.
 **
 ** The names are printed to the given file if the file pointer is non-NULL.
-** The atom is printed by giving it to the specified browser.
+** The goal is printed by giving it to the specified browser.
 */
 
-extern	const char	*MR_trace_browse_one_atom(FILE *out,
-				MR_AtomBrowser browser,
+extern	const char	*MR_trace_browse_one_goal(FILE *out,
+				MR_GoalBrowser browser,
 				MR_Browse_Caller_Type caller,
 				MR_Browse_Format format);
 
only in patch2:
--- doc/user_guide.texi	2002/01/07 07:48:10	1.284
+++ doc/user_guide.texi	2002/01/09 06:57:02
@@ -2163,6 +2163,13 @@
 The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
 and @samp{-v} or @samp{--verbose} specify the format to use for printing.
 @sp 1
+ at item print [-fpv]
+ at item print [-fpv] goal
+Prints the goal of the current call in its present state of instantiation.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for printing.
+ at sp 1
 @item print [-fpv] exception
 Prints the value of the exception at an EXCP port.
 Reports an error if the current event does not refer to such a port.
@@ -2190,6 +2197,14 @@
 For further documentation on the interactive term browser,
 invoke the @samp{browse} command from within @samp{mdb} and then
 type @samp{help} at the @samp{browser>} prompt.
+ at sp 1
+ at item browse [-fpv]
+ at item browse [-fpv] goal
+Invokes the interactive term browser to browse
+the goal of the current call in its present state of instantiation.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for browsing.
 @sp 1
 @item browse [-fpv] exception
 Invokes the interactive term browser to browse
--------------------------------------------------------------------------
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