for review: term browser (version one) (revised diff)

Bert THOMPSON aet at cs.mu.OZ.AU
Fri Oct 23 16:15:13 AEST 1998


People,

This is a relative diff showing changes to the browser after review.
Best read in conjunction with Fergus's original feedback.

Bert

===================================================================
Estimated hours taken: 50

Add a simple term browser for use by the trace-based debugger.

This is minimal but useful browser. Not included in this version
are a scripting language, Windows Explorer-style tree expansion,
and other features not yet thought of.

N.B. This still needs to be hooked into the debugger.

browser/Mmakefile:
	Added target browse_test.

browser/browser_library.m:
	Added modules required for the browser.

browser/browse_test.m:
	A simple driver for the browser with an example
	data structure to browse. (new file)

browser/browse.m:
	The browser proper. (new file)

browser/parse.m:
	Parser for browser's command language. (new file)

browser/util.m:
	Miscellaneous utilities used in the browser code. (new file)

browser/frame.m:
	Bare minimal ASCII graphics frames. (new file)


== browse.m =================================================
*** 1.11	1998/10/16 04:36:56
--- browse.m	1998/10/23 06:05:29
***************
*** 20,39 ****
  
  :- interface.
  
! :- import_module io, std_util.
  
  	% The interactive term browser.
! :- pred browse__browser(univ, io__state, io__state).
! :- mode browse__browser(in, di, uo) is det.
  
! %---------------------------------------------------------------------------%
! :- implementation.
! 
! :- import_module parse, util, frame, string, list, parser, require,
! 	std_util, int, char.
  
- :- pragma export(browse__browser(in, di, uo), "ML_browser").
- 
  :- type browser_state
  	--->	browser_state(
  			univ,	% term to browse (as univ)
--- 20,35 ----
  
  :- interface.
  
! :- import_module parse.
! :- import_module io, std_util, list.
  
  	% The interactive term browser.
! :- pred browse__browse(univ, io__state, io__state).
! :- mode browse__browse(in, di, uo) is det.
  
! :- pred browse__portray_root(browser_state, string).
! :- mode browse__portray_root(in, out) is det.
  
  :- type browser_state
  	--->	browser_state(
  			univ,	% term to browse (as univ)
***************
*** 45,65 ****
  			int	% Y clipping for verbose display
  		).
  
! browse__browser(Univ) -->
  	{ default_state(Univ, State) },
! 	startup_message,
! 	browser2(State).
  
! :- pred browser2(browser_state, io__state, io__state).
! :- mode browser2(in, di, uo) is det.
! browser2(State) -->
  	prompt,
  	parse__read_command(Command),
  	( { Command = quit } ->
! 		io__write_string("quitting...\n")
  	;
  		run_command(Command, State, NewState),
! 		browser2(NewState)
  	).
  
  :- pred startup_message(io__state::di, io__state::uo) is det.
--- 41,71 ----
  			int	% Y clipping for verbose display
  		).
  
! %---------------------------------------------------------------------------%
! :- implementation.
! 
! :- import_module parse, util, frame, string, list, parser, require,
! 	std_util, int, char.
! 
! :- pragma export(browse__browse(in, di, uo), "ML_browse").
! 
! 
! browse__browse(Univ) -->
  	{ default_state(Univ, State) },
! 	% startup_message,
! 	browse_2(State).
  
! :- pred browse_2(browser_state, io__state, io__state).
! :- mode browse_2(in, di, uo) is det.
! browse_2(State) -->
  	prompt,
  	parse__read_command(Command),
  	( { Command = quit } ->
! 		% io__write_string("quitting...\n")
! 		{ true }
  	;
  		run_command(Command, State, NewState),
! 		browse_2(NewState)
  	).
  
  :- pred startup_message(io__state::di, io__state::uo) is det.
***************
*** 77,83 ****
  :- mode run_command(in, in, out, di, uo) is det.
  run_command(Command, State, NewState) -->
  	( { Command = unknown } ->
! 		io__write_string("error: unknown command. try \"help\"\n"),
  		{ NewState = State }
  	; { Command = help } ->
  		help,
--- 83,89 ----
  :- mode run_command(in, in, out, di, uo) is det.
  run_command(Command, State, NewState) -->
  	( { Command = unknown } ->
! 		io__write_string("error: Try \"help\".\n"),
  		{ NewState = State }
  	; { Command = help } ->
  		help,
***************
*** 103,110 ****
  	; { Command = ls } ->
  		portray(State),
  		{ NewState = State }
  	; { Command = cd } ->
! 		{ set_path(root_rel([]),State, NewState) }
  	; { Command = cd(Path) } ->
  		{ get_dirs(State, Pwd) },
  		{ get_term(State, Univ) },
--- 109,119 ----
  	; { Command = ls } ->
  		portray(State),
  		{ NewState = State }
+ 	; { Command = ls(Path) } ->
+ 		portray_path(State, Path),
+ 		{ NewState = State }
  	; { Command = cd } ->
! 		{ set_path(root_rel([]), State, NewState) }
  	; { Command = cd(Path) } ->
  		{ get_dirs(State, Pwd) },
  		{ get_term(State, Univ) },
***************
*** 128,134 ****
  		{ NewState = State }
  	).
  
- 	% XXX: hardwired constant 10 in help.
  :- pred help(io__state::di, io__state::uo) is det.
  help -->
  	io__write_string(
--- 137,142 ----
***************
*** 139,159 ****
  \tset var value  -- set a setting\n\
  \tset            -- show settings\n\
  \tprint          -- show single line representation of current term\n\
- \tdisplay        -- not implemented\n\
- \twrite          -- not implemented\n\
  \tquit           -- quit browser\n\
  SICStus Prolog style commands are:\n\
- \td              -- display\n\
  \tp              -- print\n\
- \tw              -- write\n\
  \t< [n]          -- set depth (default is 10)\n\
! \t^ [path]       -- cd\n\
  \t?              -- help\n\
  \th              -- help\n\
  \n\
  -- settings:\n\
  --    size; depth; path; format (flat pretty verbose); clipx; clipy\n\
! --    example paths: /1/2/2 1/2\n\
  \n"
  	).
  
--- 147,163 ----
  \tset var value  -- set a setting\n\
  \tset            -- show settings\n\
  \tprint          -- show single line representation of current term\n\
  \tquit           -- quit browser\n\
  SICStus Prolog style commands are:\n\
  \tp              -- print\n\
  \t< [n]          -- set depth (default is 10)\n\
! \t^ [path]       -- cd [path]\n\
  \t?              -- help\n\
  \th              -- help\n\
  \n\
  -- settings:\n\
  --    size; depth; path; format (flat pretty verbose); clipx; clipy\n\
! --    Paths can be Unix-style or SICStus-style: /2/3/1 or ^2^3^1\n\
  \n"
  	).
  
***************
*** 163,190 ****
  :- mode portray(in, di, uo) is det.
  portray(State) -->
  	{ get_fmt(State, Fmt) },
! 	( { Fmt = flat } ->
  		portray_flat(State)
! 	; { Fmt = pretty } ->
  		portray_pretty(State)
- 	; { Fmt = verbose } ->
- 		portray_verbose(State)
  	;
! 		{ error("portray: unknown format") }
  	).
! 	
  
  :- pred portray_fmt(browser_state, portray_format, io__state, io__state).
  :- mode portray_fmt(in, in, di, uo) is det.
  portray_fmt(State, Format) -->
! 	( { Format = flat } ->
  		portray_flat(State)
! 	; { Format = pretty } ->
  		portray_pretty(State)
- 	; { Format = verbose } ->
- 		portray_verbose(State)
  	;
! 		{ error("portray_fmt: unknown format") }
  	).
  
  	% XXX: could abstract out the code common to the following preds.
--- 167,202 ----
  :- mode portray(in, di, uo) is det.
  portray(State) -->
  	{ get_fmt(State, Fmt) },
! 	(
! 		{ Fmt = flat },
  		portray_flat(State)
! 	;
! 		{ Fmt = pretty },
  		portray_pretty(State)
  	;
! 		{ Fmt = verbose },
! 		portray_verbose(State)
  	).
! 
! 
! :- pred portray_path(browser_state, path, io__state, io__state).
! :- mode portray_path(in, in, di, uo) is det.
! portray_path(State, Path) -->
! 	{ set_path(Path, State, NewState) },
! 	portray(NewState).
  
  :- pred portray_fmt(browser_state, portray_format, io__state, io__state).
  :- mode portray_fmt(in, in, di, uo) is det.
  portray_fmt(State, Format) -->
! 	(
! 		{ Format = flat },
  		portray_flat(State)
! 	;
! 		{ Format = pretty },
  		portray_pretty(State)
  	;
! 		{ Format = verbose },
! 		portray_verbose(State)
  	).
  
  	% XXX: could abstract out the code common to the following preds.
***************
*** 230,236 ****
  	{ get_term(State, Univ) },
  	{ get_dirs(State, Dir) },
  	( { deref_subterm(Univ, Dir, SubUniv) } ->
! 		{ term_to_string_indented(SubUniv, MaxSize, MaxDepth, Str) },
  		io__write_string(Str)
  	;
  		io__write_string("error: no such subterm")
--- 242,248 ----
  	{ get_term(State, Univ) },
  	{ get_dirs(State, Dir) },
  	( { deref_subterm(Univ, Dir, SubUniv) } ->
! 		{ term_to_string_pretty(SubUniv, MaxSize, MaxDepth, Str) },
  		io__write_string(Str)
  	;
  		io__write_string("error: no such subterm")
***************
*** 238,243 ****
--- 250,334 ----
  	io__nl.
  
  %---------------------------------------------------------------------------%
+ 	% Non-interactive display
+ 
+ 	% Display from the root term.
+ 	% This avoid errors due to dereferencing non-existent subterms.
+ browse__portray_root(State, Str) :-
+ 	get_fmt(State, Fmt),
+ 	set_path(root_rel([]), State, NewState),
+ 	(
+ 		Fmt = flat,
+ 		portray_flat_string(NewState, Str)
+ 	;
+ 		Fmt = pretty,
+ 		portray_pretty_string(NewState, Str)
+ 	;
+ 		Fmt = verbose,
+ 		portray_verbose_string(NewState, Str)
+ 	).
+ 
+ :- pred portray_string(browser_state, string).
+ :- mode portray_string(in, out) is det.
+ portray_string(State, Str) :-
+ 	get_fmt(State, Fmt),
+ 	(
+ 		Fmt = flat,
+ 		portray_flat_string(State, Str)
+ 	;
+ 		Fmt = pretty,
+ 		portray_pretty_string(State, Str)
+ 	;
+ 		Fmt = verbose,
+ 		portray_verbose_string(State, Str)
+ 	).
+ 
+ 
+ :- pred portray_flat_string(browser_state, string).
+ :- mode portray_flat_string(in, out) is det.
+ portray_flat_string(State, Str) :-
+ 	get_term(State, Univ),
+ 	get_size(State, MaxSize),
+ 	get_depth(State, MaxDepth),
+ 	get_dirs(State, Dir),
+ 	( deref_subterm(Univ, Dir, SubUniv) ->
+ 		term_to_string(SubUniv, MaxSize, MaxDepth, Str)
+ 	;
+ 		error("error: no such subterm")
+ 	).
+ 	
+ 	% XXX: return maybe(string) instead?
+ :- pred portray_pretty_string(browser_state, string).
+ :- mode portray_pretty_string(in, out) is det.
+ portray_pretty_string(State, Str) :-
+ 	get_term(State, Univ),
+ 	get_size(State, MaxSize),
+ 	get_depth(State, MaxDepth),
+ 	get_dirs(State, Dir),
+ 	( deref_subterm(Univ, Dir, SubUniv) ->
+ 		term_to_string_pretty(SubUniv, MaxSize, MaxDepth, Str)
+ 	;
+ 		error("error: no such subterm")
+ 	).
+ 	
+ :- pred portray_verbose_string(browser_state, string).
+ :- mode portray_verbose_string(in, out) is det.
+ portray_verbose_string(State, Str) :-
+ 	get_term(State, Univ),
+ 	get_size(State, MaxSize),
+ 	get_depth(State, MaxDepth),
+ 	get_dirs(State, Dir),
+ 	get_clipx(State, X),
+ 	get_clipy(State, Y),
+ 	( deref_subterm(Univ, Dir, SubUniv) ->
+ 		term_to_string_verbose(SubUniv, MaxSize, MaxDepth,
+ 			X, Y, Str)
+ 	;
+ 		error("error: no such subterm")
+ 	).
+ 	
+ 
+ %---------------------------------------------------------------------------%
  	% Single-line representation of a term.
  
  :- pred term_to_string(univ, int, int, string).
***************
*** 245,266 ****
  term_to_string(Univ, MaxSize, MaxDepth, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string2(Univ, 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.
  	% XXX: Is this reasonable?
! :- pred term_to_string2(univ, int, int, int, int, int, string).
! :- mode term_to_string2(in, in, in, out, in, in, out) is det.
! term_to_string2(Univ, MaxSize, CurSize, NewSize, MaxDepth, CurDepth, Str) :-
  	( ( (CurSize >= MaxSize) ; (CurDepth >= MaxDepth) ) ->
  		% Str = "...",
  		term_compress(Univ, Str),
  		NewSize = CurSize
  	;
! 		util__functor(Univ, Functor),
! 		util__args(Univ, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
  		term_to_string_list(Args, MaxSize, CurSize1, NewSize,
--- 336,356 ----
  term_to_string(Univ, MaxSize, MaxDepth, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string_2(Univ, 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.
  	% 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) :-
  	( ( (CurSize >= MaxSize) ; (CurDepth >= MaxDepth) ) ->
  		% Str = "...",
  		term_compress(Univ, Str),
  		NewSize = CurSize
  	;
! 		deconstruct(Univ, Functor, _Arity, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
  		term_to_string_list(Args, MaxSize, CurSize1, NewSize,
***************
*** 275,287 ****
  		_MaxDepth, _CurDepth, Strs) :-
  	Strs = [],
  	NewSize = CurSize.
! term_to_string_list([Univ|Univs], MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Strs) :-
! 	term_to_string2(Univ, MaxSize, CurSize, NewSize1,
  		MaxDepth, CurDepth, Str),
  	term_to_string_list(Univs, MaxSize, NewSize1, NewSize,
  		MaxDepth, CurDepth, RestStrs),
! 	Strs = [Str|RestStrs].
  
  
  :- pred brack_args(list(string), string).
--- 365,377 ----
  		_MaxDepth, _CurDepth, Strs) :-
  	Strs = [],
  	NewSize = CurSize.
! term_to_string_list([Univ | Univs], MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Strs) :-
! 	term_to_string_2(Univ, MaxSize, CurSize, NewSize1,
  		MaxDepth, CurDepth, Str),
  	term_to_string_list(Univs, MaxSize, NewSize1, NewSize,
  		MaxDepth, CurDepth, RestStrs),
! 	Strs = [Str | RestStrs].
  
  
  :- pred brack_args(list(string), string).
***************
*** 297,318 ****
  :- pred comma_args(list(string), string).
  :- mode comma_args(in, out) is det.
  comma_args(Args, Str) :-
! 	( Args = [] ->
  		Str = ""
! 	; Args = [S] ->
  		Str = S
- 	; Args = [S1,S2|Ss] ->
- 		comma_args([S2|Ss], Rest),
- 		string__append_list([S1, ", ", Rest], Str)
  	;
! 		error("comma_args: software error")
  	).
  
  :- pred term_compress(univ, string).
  :- mode term_compress(in, out) is det.
  term_compress(Univ, Str) :-
! 	util__functor(Univ, Functor),
! 	util__arity(Univ, Arity),
  	( Arity = 0 ->
  		Str = Functor
  	;
--- 387,408 ----
  :- pred comma_args(list(string), string).
  :- mode comma_args(in, out) is det.
  comma_args(Args, Str) :-
! 	(
! 		Args = [],
  		Str = ""
! 	;
! 		Args = [S],
  		Str = S
  	;
! 		Args = [S1, S2 | Ss],
! 		comma_args([S2 | Ss], Rest),
! 		string__append_list([S1, ", ", Rest], Str)
  	).
  
  :- pred term_compress(univ, string).
  :- mode term_compress(in, out) is det.
  term_compress(Univ, Str) :-
! 	deconstruct(Univ, Functor, Arity, _Args),
  	( Arity = 0 ->
  		Str = Functor
  	;
***************
*** 326,345 ****
  	% pretty printing since parentheses and commas are omitted.
  	% XXX: Should do proper pretty printing?
  
! :- pred term_to_string_indented(univ, int, int, string).
! :- mode term_to_string_indented(in, in, in, out) is det.
! term_to_string_indented(Univ, MaxSize, MaxDepth, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string_indented2(Univ, MaxSize, CurSize, _NewSize,
  		MaxDepth, CurDepth, Lines),
  	unlines(Lines, Str).
  
! :- pred term_to_string_indented2(univ, int, int, int, int, int, list(string)).
! 
! :- mode term_to_string_indented2(in, in, in, out, in, in, out) is det.
! 
! term_to_string_indented2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Lines) :-
  	( ((CurSize >= MaxSize) ; (CurDepth >= MaxDepth)) ->
  		term_compress(Univ, Line),
--- 416,433 ----
  	% pretty printing since parentheses and commas are omitted.
  	% XXX: Should do proper pretty printing?
  
! :- pred term_to_string_pretty(univ, int, int, string).
! :- mode term_to_string_pretty(in, in, in, out) is det.
! term_to_string_pretty(Univ, MaxSize, MaxDepth, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string_pretty_2(Univ, MaxSize, CurSize, _NewSize,
  		MaxDepth, CurDepth, Lines),
  	unlines(Lines, Str).
  
! :- pred term_to_string_pretty_2(univ, int, int, int, int, int, list(string)).
! :- mode term_to_string_pretty_2(in, in, in, out, in, in, out) is det.
! term_to_string_pretty_2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Lines) :-
  	( ((CurSize >= MaxSize) ; (CurDepth >= MaxDepth)) ->
  		term_compress(Univ, Line),
***************
*** 347,377 ****
  		% Lines = ["..."],
  		NewSize = CurSize
  	;
! 		util__functor(Univ, Functor),
! 		util__args(Univ, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
! 		term_to_string_indented_list(Args, MaxSize, CurSize1,
  			NewSize, MaxDepth, CurDepth1, ArgsLines),
  		list__condense(ArgsLines, ArgsLineses),
  		map(indent, ArgsLineses, IndentedArgLines),
! 		list__append([Functor], IndentedArgLines, Lines)
  	).
  
! :- pred term_to_string_indented_list(list(univ), int, int, int, int, int,
  	list(list(string))).
! :- mode term_to_string_indented_list(in, in, in, out, in, in, out) is det.
! term_to_string_indented_list([], _MaxSize, CurSize, NewSize,
  		_MaxDepth, _CurDepth, Lines) :-
  	Lines = [],
  	NewSize = CurSize.
! term_to_string_indented_list([Univ|Univs], MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Lineses) :-
! 	term_to_string_indented2(Univ, MaxSize, CurSize, NewSize1,
  		MaxDepth, CurDepth, Lines),
! 	term_to_string_indented_list(Univs, MaxSize, NewSize1, NewSize,
  		MaxDepth, CurDepth, RestLineses),
! 	Lineses = [Lines|RestLineses].
  	
  :- pred indent(string::in, string::out) is det.
  indent(Str, IndentedStr) :-
--- 435,490 ----
  		% Lines = ["..."],
  		NewSize = CurSize
  	;
! 		deconstruct(Univ, Functor, Arity, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
! 		( Arity >= 1 ->
! 			string__append(Functor, "(", Functor1)
! 		;
! 			Functor1 = Functor
! 		),
! 		term_to_string_pretty_list(Args, MaxSize, CurSize1,
  			NewSize, MaxDepth, CurDepth1, ArgsLines),
  		list__condense(ArgsLines, ArgsLineses),
  		map(indent, ArgsLineses, IndentedArgLines),
! 		list__append([Functor1], IndentedArgLines, Lines1),
! 		( Arity >= 1 ->
! 			list__append(Lines1, [")"], Lines)
! 		;
! 			Lines = Lines1
! 		)
  	).
  
! 
! :- pred term_to_string_pretty_list(list(univ), int, int, int, int, int,
  	list(list(string))).
! :- mode term_to_string_pretty_list(in, in, in, out, in, in, out) is det.
! term_to_string_pretty_list([], _MaxSize, CurSize, NewSize,
  		_MaxDepth, _CurDepth, Lines) :-
  	Lines = [],
  	NewSize = CurSize.
! term_to_string_pretty_list([Univ], MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Lineses) :-
! 	term_to_string_pretty_2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Lines),
! 	Lineses = [Lines].
! term_to_string_pretty_list([Univ1, Univ2 | Univs], MaxSize, CurSize, NewSize,
! 		MaxDepth, CurDepth, Lineses) :-
! 	term_to_string_pretty_2(Univ1, MaxSize, CurSize, NewSize1,
! 		MaxDepth, CurDepth, Lines1),
! 	comma_last(Lines1, Lines),
! 	term_to_string_pretty_list([Univ2 | Univs], MaxSize, NewSize1, NewSize,
  		MaxDepth, CurDepth, RestLineses),
! 	Lineses = [Lines | RestLineses].
! 
! :- pred comma_last(list(string), list(string)).
! :- mode comma_last(in, out) is det.
! comma_last([], []).
! comma_last([S], [Sc]) :-
! 	string__append(S, ",", Sc).
! comma_last([S1, S2 | Ss], [S1 | Rest]) :-
! 	comma_last([S2 | Ss], Rest).
! 
  	
  :- pred indent(string::in, string::out) is det.
  indent(Str, IndentedStr) :-
***************
*** 379,385 ****
  
  :- pred unlines(list(string)::in, string::out) is det.
  unlines([], "").
! unlines([Line|Lines], Str) :-
  	string__append(Line, "\n", NLine),
  	unlines(Lines, Strs),
  	string__append(NLine, Strs, Str).
--- 492,498 ----
  
  :- pred unlines(list(string)::in, string::out) is det.
  unlines([], "").
! unlines([Line | Lines], Str) :-
  	string__append(Line, "\n", NLine),
  	unlines(Lines, Strs),
  	string__append(NLine, Strs, Str).
***************
*** 394,407 ****
  term_to_string_verbose(Univ, MaxSize, MaxDepth, X, Y, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string_verbose2(Univ, MaxSize, CurSize, _NewSize,
  		MaxDepth, CurDepth, Frame),
  	frame__clip(X-Y, Frame, ClippedFrame),
  	unlines(ClippedFrame, Str).
  
! :- pred term_to_string_verbose2(univ, int, int, int, int, int, frame).
! :- mode term_to_string_verbose2(in, in, in, out, in, in, out) is det.
! term_to_string_verbose2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Frame) :-
  	( ((CurSize >= MaxSize) ; (CurDepth >= MaxDepth)) ->
  		term_compress(Univ, Line),
--- 507,520 ----
  term_to_string_verbose(Univ, MaxSize, MaxDepth, X, Y, Str) :-
  	CurSize = 0,
  	CurDepth = 0,
! 	term_to_string_verbose_2(Univ, MaxSize, CurSize, _NewSize,
  		MaxDepth, CurDepth, Frame),
  	frame__clip(X-Y, Frame, ClippedFrame),
  	unlines(ClippedFrame, Str).
  
! :- 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,
  		MaxDepth, CurDepth, Frame) :-
  	( ((CurSize >= MaxSize) ; (CurDepth >= MaxDepth)) ->
  		term_compress(Univ, Line),
***************
*** 408,415 ****
  		Frame = [Line],
  		NewSize = CurSize
  	;
! 		util__functor(Univ, Functor),
! 		util__args(Univ, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
  		ArgNum = 1,
--- 521,527 ----
  		Frame = [Line],
  		NewSize = CurSize
  	;
! 		deconstruct(Univ, Functor, _Arity, Args),
  		CurSize1 is CurSize + 1,
  		CurDepth1 is CurDepth + 1,
  		ArgNum = 1,
***************
*** 429,435 ****
  
  term_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Frame) :-
! 	term_to_string_verbose2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, TreeFrame),
  	% XXX: ArgNumS must have fixed length 2.
  	string__int_to_string(ArgNum, ArgNumS),
--- 541,547 ----
  
  term_to_string_verbose_list([Univ], ArgNum, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, Frame) :-
! 	term_to_string_verbose_2(Univ, MaxSize, CurSize, NewSize,
  		MaxDepth, CurDepth, TreeFrame),
  	% XXX: ArgNumS must have fixed length 2.
  	string__int_to_string(ArgNum, ArgNumS),
***************
*** 436,447 ****
  	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_verbose2(Univ1, MaxSize, CurSize, NewSize1,
  		MaxDepth, CurDepth, TreeFrame),
  	ArgNum1 is ArgNum + 1,
! 	term_to_string_verbose_list([Univ2|Univs], ArgNum1, MaxSize,
  		NewSize1, NewSize2, MaxDepth, CurDepth, RestTreesFrame),
  	NewSize = NewSize2,
  	% XXX: ArgNumS must have fixed length 2.
--- 548,559 ----
  	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),
  	ArgNum1 is ArgNum + 1,
! 	term_to_string_verbose_list([Univ2 | Univs], ArgNum1, MaxSize,
  		NewSize1, NewSize2, MaxDepth, CurDepth, RestTreesFrame),
  	NewSize = NewSize2,
  	% XXX: ArgNumS must have fixed length 2.
***************
*** 449,455 ****
  	string__append_list([ArgNumS, "-"], BranchFrameS),
  	frame__vsize(TreeFrame, Height),
  	Height1 is Height - 1,
! 	util__copy(Height1, "|", VBranchFrame),
  	frame__vglue([BranchFrameS], VBranchFrame, LeftFrame),
  	frame__hglue(LeftFrame, TreeFrame, TopFrame),
  	frame__vglue(TopFrame, RestTreesFrame, Frame).
--- 561,567 ----
  	string__append_list([ArgNumS, "-"], BranchFrameS),
  	frame__vsize(TreeFrame, Height),
  	Height1 is Height - 1,
! 	list__duplicate(Height1, "|", VBranchFrame),
  	frame__vglue([BranchFrameS], VBranchFrame, LeftFrame),
  	frame__hglue(LeftFrame, TreeFrame, TopFrame),
  	frame__vglue(TopFrame, RestTreesFrame, Frame).
***************
*** 462,499 ****
  write_path([]) -->
  	io__write_string("/").
  write_path([Dir]) -->
! 	( { Dir = parent } ->
  		io__write_string("/")
- 	; { Dir = child(N) } ->
- 		io__write_string("/"), io__write_int(N)
  	;
! 		{ error("write_path: software error") }
  	).
! write_path([Dir,Dir2|Dirs]) -->
! 	write_path2([Dir,Dir2|Dirs]).
  
  
! :- pred write_path2(list(dir), io__state, io__state).
! :- mode write_path2(in, di, uo) is det.
! write_path2([]) -->
  	io__write_string("/").
! write_path2([Dir]) -->
! 	( { Dir = parent } ->
  		io__write_string("/..")
- 	; { Dir = child(N) } ->
- 		io__write_string("/"), io__write_int(N)
  	;
! 		{ error("write_path2: software error") }
  	).
! write_path2([Dir,Dir2|Dirs]) -->
! 	( { Dir = parent } ->
  		io__write_string("/.."),
! 		write_path2([Dir2|Dirs])
! 	; { Dir = child(N) } ->
! 		io__write_string("/"), io__write_int(N),
! 		write_path2([Dir2|Dirs])
  	;
! 		{ error("write_path2: software error") }
  	).
  
  	% We assume a root-relative path. We assume Term is the entire term
--- 574,611 ----
  write_path([]) -->
  	io__write_string("/").
  write_path([Dir]) -->
! 	(
! 		{ Dir = parent },
  		io__write_string("/")
  	;
! 		{ Dir = child(N) },
! 		io__write_string("/"), io__write_int(N)
  	).
! write_path([Dir, Dir2 | Dirs]) -->
! 	write_path_2([Dir, Dir2 | Dirs]).
  
  
! :- pred write_path_2(list(dir), io__state, io__state).
! :- mode write_path_2(in, di, uo) is det.
! write_path_2([]) -->
  	io__write_string("/").
! write_path_2([Dir]) -->
! 	(
! 		{ Dir = parent },
  		io__write_string("/..")
  	;
! 		{ Dir = child(N) },
! 		io__write_string("/"), io__write_int(N)
  	).
! write_path_2([Dir, Dir2 | Dirs]) -->
! 	(
! 		{ Dir = parent },
  		io__write_string("/.."),
! 		write_path_2([Dir2 | Dirs])
  	;
! 		{ Dir = child(N) },
! 		io__write_string("/"), io__write_int(N),
! 		write_path_2([Dir2 | Dirs])
  	).
  
  	% We assume a root-relative path. We assume Term is the entire term
***************
*** 502,508 ****
  :- mode deref_subterm(in, in, out) is semidet.
  deref_subterm(Univ, Path, SubUniv) :-
  	path_to_int_list(Path, PathN),
! 	deref_subterm2(Univ, PathN, SubUniv).
  
  :- pred path_to_int_list(list(dir), list(int)).
  :- mode path_to_int_list(in, out) is semidet.
--- 614,620 ----
  :- mode deref_subterm(in, in, out) is semidet.
  deref_subterm(Univ, Path, SubUniv) :-
  	path_to_int_list(Path, PathN),
! 	deref_subterm_2(Univ, PathN, SubUniv).
  
  :- pred path_to_int_list(list(dir), list(int)).
  :- mode path_to_int_list(in, out) is semidet.
***************
*** 513,533 ****
  :- pred dirs_to_ints(list(dir), list(int)).
  :- mode dirs_to_ints(in, out) is semidet.
  dirs_to_ints([], []).
! dirs_to_ints([child(N)|Dirs], [N|Ns]) :-
  	dirs_to_ints(Dirs, Ns).
! dirs_to_ints([parent|_], _) :-
   	error("dirs_to_ints: software error").
  
! :- pred deref_subterm2(univ, list(int), univ) is semidet.
! :- mode deref_subterm2(in, in, out) is semidet.
! deref_subterm2(Univ, Path, SubUniv) :-
  	( Path = [] ->
  		Univ = SubUniv
  	; 
! 		Path = [N|Ns],
! 		util__args(Univ, Args),
  		list__index1(Args, N, ArgN),
! 		deref_subterm2(ArgN, Ns, SubUniv)
  	).
  
  %---------------------------------------------------------------------------%
--- 625,645 ----
  :- pred dirs_to_ints(list(dir), list(int)).
  :- mode dirs_to_ints(in, out) is semidet.
  dirs_to_ints([], []).
! dirs_to_ints([child(N) | Dirs], [N | Ns]) :-
  	dirs_to_ints(Dirs, Ns).
! dirs_to_ints([parent | _], _) :-
   	error("dirs_to_ints: software error").
  
! :- pred deref_subterm_2(univ, list(int), univ) is semidet.
! :- mode deref_subterm_2(in, in, out) is semidet.
! deref_subterm_2(Univ, Path, SubUniv) :-
  	( Path = [] ->
  		Univ = SubUniv
  	; 
! 		Path = [N | Ns],
! 		deconstruct(Univ, _Functor, _Arity, Args),
  		list__index1(Args, N, ArgN),
! 		deref_subterm_2(ArgN, Ns, SubUniv)
  	).
  
  %---------------------------------------------------------------------------%
***************
*** 536,542 ****
  :- pred default_state(univ, browser_state).
  :- mode default_state(in, out) is det.
  default_state(Univ, State) :-
! 	State = browser_state(Univ,3,10,[],verbose, 79, 25).
  
  :- pred get_term(browser_state, univ).
  :- mode get_term(in, out) is det.
--- 648,655 ----
  :- pred default_state(univ, browser_state).
  :- mode default_state(in, out) is det.
  default_state(Univ, State) :-
! 	State = browser_state(Univ, 3, DefaultDepth, [], verbose, 79, 25),
! 	default_depth(DefaultDepth).
  
  :- pred get_term(browser_state, univ).
  :- mode get_term(in, out) is det.
***************
*** 605,616 ****
  :- pred change_dir(list(dir), path, list(dir)).
  :- mode change_dir(in, in, out) is det.
  change_dir(PwdDirs, Path, RootRelDirs) :-
! 	( Path = root_rel(Dirs) ->
  		NewDirs = Dirs
- 	; Path = dot_rel(Dirs) ->
- 		list__append(PwdDirs, Dirs, NewDirs)
  	;
! 		error("change_dir: software error")
  	),
  	simplify_dirs(NewDirs, RootRelDirs).
  
--- 718,729 ----
  :- pred change_dir(list(dir), path, list(dir)).
  :- mode change_dir(in, in, out) is det.
  change_dir(PwdDirs, Path, RootRelDirs) :-
! 	(
! 		Path = root_rel(Dirs),
  		NewDirs = Dirs
  	;
! 		Path = dot_rel(Dirs),
! 		list__append(PwdDirs, Dirs, NewDirs)
  	),
  	simplify_dirs(NewDirs, RootRelDirs).
  
***************
*** 621,628 ****
  
  :- pred set_term(univ, browser_state, browser_state).
  :- mode set_term(in, in, out) is det.
! set_term(NewUniv, browser_state(_OldUniv,Dep,Siz,Path,Fmt,X,Y),
! 	browser_state(NewUniv,Dep,Siz,Path,Fmt,X,Y)).
  
  %---------------------------------------------------------------------------%
  	% display predicates.
--- 734,741 ----
  
  :- pred set_term(univ, browser_state, browser_state).
  :- mode set_term(in, in, out) is det.
! set_term(NewUniv, browser_state(_OldUniv, Dep, Siz, Path, Fmt, X, Y),
! 	browser_state(NewUniv, Dep, Siz, Path, Fmt, X, Y)).
  
  %---------------------------------------------------------------------------%
  	% display predicates.
***************
*** 639,654 ****
  	io__write_string("Current path is: "),
  		write_path(CurPath), io__nl,
  	io__write_string("Print format is "),
! 		io__write_string(FmtStr), io__nl,
! 	( { Fmt = flat } ->
! 		{ FmtStr = "flat" }
! 	; { Fmt = pretty } ->
! 		{ FmtStr = "pretty" }
! 	; { Fmt = verbose } ->
! 		{ FmtStr = "verbose" }
! 	;
! 		{ error("show_settings: unknown format") }
! 	).
  
  :- pred string_to_path(string, path).
  :- mode string_to_path(in, out) is semidet.
--- 752,759 ----
  	io__write_string("Current path is: "),
  		write_path(CurPath), io__nl,
  	io__write_string("Print format is "),
! 	io__print(Fmt),
! 	io__nl.
  
  :- pred string_to_path(string, path).
  :- mode string_to_path(in, out) is semidet.
***************
*** 658,670 ****
  
  :- pred chars_to_path(list(char), path).
  :- mode chars_to_path(in, out) is semidet.
! chars_to_path([C|Cs], Path) :-
  	( C = ('/') ->
  		Path = root_rel(Dirs),
  		chars_to_dirs(Cs, Dirs)
  	;
  		Path = dot_rel(Dirs),
! 		chars_to_dirs([C|Cs], Dirs)
  	).
  
  :- pred chars_to_dirs(list(char), list(dir)).
--- 763,775 ----
  
  :- pred chars_to_path(list(char), path).
  :- mode chars_to_path(in, out) is semidet.
! chars_to_path([C | Cs], Path) :-
  	( C = ('/') ->
  		Path = root_rel(Dirs),
  		chars_to_dirs(Cs, Dirs)
  	;
  		Path = dot_rel(Dirs),
! 		chars_to_dirs([C | Cs], Dirs)
  	).
  
  :- pred chars_to_dirs(list(char), list(dir)).
***************
*** 676,690 ****
  :- pred names_to_dirs(list(string), list(dir)).
  :- mode names_to_dirs(in, out) is semidet.
  names_to_dirs([], []).
! names_to_dirs([Name|Names], Dirs) :-
  	( Name = ".." ->
! 		Dirs = [parent|RestDirs],
  		names_to_dirs(Names, RestDirs)
  	; Name = "." ->
  		names_to_dirs(Names, Dirs)
  	;
  		string__to_int(Name, Num),
! 		Dirs = [child(Num)| RestDirs],
  		names_to_dirs(Names, RestDirs)
  	).
  
--- 781,795 ----
  :- pred names_to_dirs(list(string), list(dir)).
  :- mode names_to_dirs(in, out) is semidet.
  names_to_dirs([], []).
! names_to_dirs([Name | Names], Dirs) :-
  	( Name = ".." ->
! 		Dirs = [parent | RestDirs],
  		names_to_dirs(Names, RestDirs)
  	; Name = "." ->
  		names_to_dirs(Names, Dirs)
  	;
  		string__to_int(Name, Num),
! 		Dirs = [child(Num) | RestDirs],
  		names_to_dirs(Names, RestDirs)
  	).
  
***************
*** 698,706 ****
  		Names = []
  	; Rest = [] ->
  		Names = [Name]
! 	; Rest = [_Slash|RestCs] ->
  		split_dirs(RestCs, RestNames),
! 		Names = [Name|RestNames]
  	;
  		error("split_dirs: software error")
  	).
--- 803,811 ----
  		Names = []
  	; Rest = [] ->
  		Names = [Name]
! 	; Rest = [_Slash | RestCs] ->
  		split_dirs(RestCs, RestNames),
! 		Names = [Name | RestNames]
  	;
  		error("split_dirs: software error")
  	).
***************
*** 711,728 ****
  not_slash(C) :-
  	C \= ('/').
  
  :- pred simplify_dirs(list(dir), list(dir)).
  :- mode simplify_dirs(in, out) is det.
  simplify_dirs(Dirs, SimpleDirs) :-
  	util__limit(simplify, Dirs, SimpleDirs).
  
  :- pred simplify(list(dir), list(dir)).
  :- mode simplify(in, out) is det.
  simplify([], []).
! simplify([parent|Dirs], Dirs).
  simplify([child(Dir)], [child(Dir)]).
! simplify([child(_Dir), parent |Dirs], Dirs).
! simplify([child(Dir1), child(Dir2) |Dirs], [child(Dir1) | Rest]) :-
! 	simplify([child(Dir2)|Dirs], Rest).
  
  %---------------------------------------------------------------------------%
--- 816,843 ----
  not_slash(C) :-
  	C \= ('/').
  
+ 	% Remove "/dir/../" sequences from a list of directories to yield
+ 	% a form that lacks ".." entries.
+ 	% NB: This can be done more efficiently than simple iteration
+ 	% to a limit.
  :- pred simplify_dirs(list(dir), list(dir)).
  :- mode simplify_dirs(in, out) is det.
  simplify_dirs(Dirs, SimpleDirs) :-
  	util__limit(simplify, Dirs, SimpleDirs).
  
+ 	% If possible, remove a single occurence of
+ 	% either:
+ 	%	- "dir/../"
+ 	% or:
+ 	%	- "/.." (parent of root is root)
+ 	%
  :- pred simplify(list(dir), list(dir)).
  :- mode simplify(in, out) is det.
  simplify([], []).
! simplify([parent | Dirs], Dirs).
  simplify([child(Dir)], [child(Dir)]).
! simplify([child(_Dir), parent | Dirs], Dirs).
! simplify([child(Dir1), child(Dir2) | Dirs], [child(Dir1) | Rest]) :-
! 	simplify([child(Dir2) | Dirs], Rest).
  
  %---------------------------------------------------------------------------%
== browse_test.m =================================================
*** 1.7	1998/10/16 04:27:37
--- browse_test.m	1998/10/16 04:29:43
***************
*** 37,43 ****
  			AssocList) },
  		{ tree234__assoc_list_to_tree234(AssocList, Tree) },
  		{ type_to_univ(Tree, Univ) },
! 		browse__browser(Univ),
  		io__set_exit_status(EXIT_SUCCESS)
  	).
  
--- 37,43 ----
  			AssocList) },
  		{ tree234__assoc_list_to_tree234(AssocList, Tree) },
  		{ type_to_univ(Tree, Univ) },
! 		browse__browse(Univ),
  		io__set_exit_status(EXIT_SUCCESS)
  	).
  
== frame.m =================================================
*** 1.6	1998/10/16 04:25:30
--- frame.m	1998/10/23 04:08:50
***************
*** 21,27 ****
  :- import_module list, std_util.
  
  	% XXX: Make frame type abstract instead?
- 	% XXX: I'd rather not fully module-qualify the frame type.
  % :- type frame.
  :- type frame == list(string).
  
--- 21,26 ----
***************
*** 29,49 ****
--- 28,54 ----
  	% coordinates is needed.
  :- type frame__clip_rect == pair(int, int).
  
+ 	% Width of a frame (horizontal size).
  :- pred frame__hsize(frame, int).
  :- mode frame__hsize(in, out) is det.
  
+ 	% Height of a frame (vertical size).
  :- pred frame__vsize(frame, int).
  :- mode frame__vsize(in, out) is det.
  
+ 	% Create a frame from a string.
  :- pred frame__from_string(string, frame).
  :- mode frame__from_string(in, out) is det.
  
+ 	% Stack (vertically glue) two frames, left-aligned.
  :- pred frame__vglue(frame, frame, frame).
  :- mode frame__vglue(in, in, out) is det.
  
+ 	% Juxtapose (horizontally glue) two frames, top-aligned.
  :- pred frame__hglue(frame, frame, frame).
  :- mode frame__hglue(in, in, out) is det.
  
+ 	% clip a frame, where cliprect originates in top-left corner of frame.
  :- pred frame__clip(frame__clip_rect, frame, frame).
  :- mode frame__clip(in, in, out) is det.
  
***************
*** 101,107 ****
  	( (Strs = [], Lens = []) ->
  		PaddedFrame = []
  	; (Strs = [S|Ss], Lens = [L|Ls]) ->
! 		util__copy(L, ' ', PadChars),
  		string__from_char_list(PadChars, Padding),
  		string__append(S, Padding, SP),
  		add_right_padding(Ss, Ls, Rest),
--- 106,112 ----
  	( (Strs = [], Lens = []) ->
  		PaddedFrame = []
  	; (Strs = [S|Ss], Lens = [L|Ls]) ->
! 		list__duplicate(L, ' ', PadChars),
  		string__from_char_list(PadChars, Padding),
  		string__append(S, Padding, SP),
  		add_right_padding(Ss, Ls, Rest),
***************
*** 121,127 ****
  :- pred frame_lower_pad(frame, int, frame).
  :- mode frame_lower_pad(in, in, out) is det.
  frame_lower_pad(Frame, PadLines, PaddedFrame) :-
! 	util__copy(PadLines, "", Padding),
  	list__append(Frame, Padding, PaddedFrame).
  
  
--- 126,132 ----
  :- pred frame_lower_pad(frame, int, frame).
  :- mode frame_lower_pad(in, in, out) is det.
  frame_lower_pad(Frame, PadLines, PaddedFrame) :-
! 	list__duplicate(PadLines, "", Padding),
  	list__append(Frame, Padding, PaddedFrame).
  
  
***************
*** 137,143 ****
  
  	% Clip a frame to the rectangle ((0,0),(X,Y)) where
  	% origin is on the top-left. Coordinate axes go down and right.
- 	% XXX: Any reasons to implement a general clip?
  frame__clip(X-Y, Frame, ClippedFrame) :-
  	list__take_upto(Y, Frame, YClippedFrame),
  	list__map(left(X), YClippedFrame, ClippedFrame).
--- 142,147 ----
== parse.m =================================================
*** 1.5	1998/10/16 04:26:20
--- parse.m	1998/10/23 04:11:46
***************
*** 37,46 ****
  %		"verbose"
  %
  %	path:
! %		["/"] dir ["/" path]
  %
  %	dir:
  %		num
  %
  
  :- module parse.
--- 37,50 ----
  %		"verbose"
  %
  %	path:
! %		["/"] [dirs]
  %
+ %	dirs:
+ %		dir ["/" dirs]
+ %
  %	dir:
  %		num
+ %		".."
  %
  
  :- module parse.
***************
*** 49,55 ****
  
  :- import_module io, list.
  
- 	% XXX: could nuke zero-arity "ls" and "cd".
  :- type command
  	--->	ls(path)
  	;	ls
--- 53,58 ----
***************
*** 90,95 ****
--- 93,101 ----
  :- pred parse__read_command(command, io__state, io__state).
  :- mode parse__read_command(out, di, uo) is det.
  
+ :- pred default_depth(int).
+ :- mode default_depth(out) is det.
+ 
  %---------------------------------------------------------------------------%
  :- implementation.
  
***************
*** 125,148 ****
  
  :- pred lexer(list(char), list(token)).
  :- mode lexer(in, out) is det.
! lexer([],[]).
! lexer([C|Cs], Toks) :-
  	( C = ('.') ->
  		lexer_dots(Cs, Toks)
  	; C = ('/') ->
! 		Toks = [(/)|Toks2],
  		lexer(Cs, Toks2)
  	; C = ('?') ->
! 		Toks = [(?)|Toks2],
  		lexer(Cs, Toks2)
  	; C = ('^') ->
! 		Toks = [(^)|Toks2],
  		lexer(Cs, Toks2)
  	; C = ('<') ->
! 		Toks = [(<)|Toks2],
  		lexer(Cs, Toks2)
  	; char__is_digit(C) ->
! 		dig_to_int(C,N),
  		lexer_num(N, Cs, Toks)
  	; char__is_alpha(C) ->
  		lexer_name(C, Cs, Toks)
--- 131,154 ----
  
  :- pred lexer(list(char), list(token)).
  :- mode lexer(in, out) is det.
! lexer([], []).
! lexer([C | Cs], Toks) :-
  	( C = ('.') ->
  		lexer_dots(Cs, Toks)
  	; C = ('/') ->
! 		Toks = [(/) | Toks2],
  		lexer(Cs, Toks2)
  	; C = ('?') ->
! 		Toks = [(?) | Toks2],
  		lexer(Cs, Toks2)
  	; C = ('^') ->
! 		Toks = [(^) | Toks2],
  		lexer(Cs, Toks2)
  	; C = ('<') ->
! 		Toks = [(<) | Toks2],
  		lexer(Cs, Toks2)
  	; char__is_digit(C) ->
! 		dig_to_int(C, N),
  		lexer_num(N, Cs, Toks)
  	; char__is_alpha(C) ->
  		lexer_name(C, Cs, Toks)
***************
*** 149,170 ****
  	; char__is_whitespace(C) ->
  		lexer(Cs, Toks)
  	;
! 		Toks = [unknown(C) |Toks2],
  		lexer(Cs, Toks2)
  	).
  
  :- pred lexer_dots(list(char), list(token)).
  :- mode lexer_dots(in, out) is det.
! lexer_dots([],[]).
! lexer_dots([C|Cs], Toks) :-
  	( C = ('.') ->
  		Tok = (..),
  		lexer(Cs, Toks2),
! 		Toks = [Tok|Toks2]
  	;
  		Tok = (.),
! 		lexer([C|Cs], Toks2),
! 		Toks = [Tok|Toks2]
  	).
  
  :- pred dig_to_int(char, int).
--- 155,176 ----
  	; char__is_whitespace(C) ->
  		lexer(Cs, Toks)
  	;
! 		Toks = [unknown(C) | Toks2],
  		lexer(Cs, Toks2)
  	).
  
  :- pred lexer_dots(list(char), list(token)).
  :- mode lexer_dots(in, out) is det.
! lexer_dots([], []).
! lexer_dots([C | Cs], Toks) :-
  	( C = ('.') ->
  		Tok = (..),
  		lexer(Cs, Toks2),
! 		Toks = [Tok | Toks2]
  	;
  		Tok = (.),
! 		lexer([C | Cs], Toks2),
! 		Toks = [Tok | Toks2]
  	).
  
  :- pred dig_to_int(char, int).
***************
*** 179,185 ****
  lexer_num(N, Cs, Toks) :-
  	list__takewhile(char__is_digit, Cs, Digits, Rest),
  	digits_to_int_acc(N, Digits, Num),
! 	Toks = [num(Num)|Toks2],
  	lexer(Rest, Toks2).
  	
  			
--- 185,191 ----
  lexer_num(N, Cs, Toks) :-
  	list__takewhile(char__is_digit, Cs, Digits, Rest),
  	digits_to_int_acc(N, Digits, Num),
! 	Toks = [num(Num) | Toks2],
  	lexer(Rest, Toks2).
  	
  			
***************
*** 186,192 ****
  :- pred digits_to_int_acc(int, list(char), int).
  :- mode digits_to_int_acc(in, in, out) is det.
  digits_to_int_acc(Acc, [], Acc).
! digits_to_int_acc(Acc, [C|Cs], Num) :-
  	dig_to_int(C, D),
  	Acc2 is 10 * Acc + D,
  	digits_to_int_acc(Acc2, Cs, Num).
--- 192,198 ----
  :- pred digits_to_int_acc(int, list(char), int).
  :- mode digits_to_int_acc(in, in, out) is det.
  digits_to_int_acc(Acc, [], Acc).
! digits_to_int_acc(Acc, [C | Cs], Num) :-
  	dig_to_int(C, D),
  	Acc2 is 10 * Acc + D,
  	digits_to_int_acc(Acc2, Cs, Num).
***************
*** 196,204 ****
  :- mode lexer_name(in, in, out) is det.
  lexer_name(C, Cs, Toks) :-
  	list__takewhile(char__is_alpha, Cs, Letters, Rest),
! 	string__from_char_list([C|Letters], Name),
  	lexer(Rest, Toks2),
! 	Toks = [name(Name)|Toks2].
  	
  
  :- pred parse(list(token), command).
--- 202,210 ----
  :- mode lexer_name(in, in, out) is det.
  lexer_name(C, Cs, Toks) :-
  	list__takewhile(char__is_alpha, Cs, Letters, Rest),
! 	string__from_char_list([C | Letters], Name),
  	lexer(Rest, Toks2),
! 	Toks = [name(Name) | Toks2].
  	
  
  :- pred parse(list(token), command).
***************
*** 208,214 ****
  
  :- pred start(list(token), command).
  :- mode start(in, out) is semidet.
! start([Tok|Toks], Comm) :-
  	( (Tok = name("help") ; Tok = (?) ; Tok = name("h")) ->
  		Toks = [],
  		Comm = help
--- 214,220 ----
  
  :- pred start(list(token), command).
  :- mode start(in, out) is semidet.
! start([Tok | Toks], Comm) :-
  	( (Tok = name("help") ; Tok = (?) ; Tok = name("h")) ->
  		Toks = [],
  		Comm = help
***************
*** 259,267 ****
  		)
  	).
  
- 	% XXX: default depth also in browse.m
- :- pred default_depth(int).
- :- mode default_depth(out) is det.
  default_depth(10).
  
  :- pred parse_path(list(token), path).
--- 265,270 ----
***************
*** 268,300 ****
  :- mode parse_path(in, out) is semidet.
  	% SICStus is forgiving in the syntax of paths, hence so are we.
  	% XXX: Be less forgiving?
! parse_path([Tok|Toks], Path) :-
  	( Tok = (/) ->
  		Path = root_rel(Dirs),
  		parse_dirs(Toks, Dirs)
  	;
  		Path = dot_rel(Dirs),
! 		parse_dirs([Tok|Toks], Dirs)
  	).
  
  :- pred parse_dirs(list(token), list(dir)).
  :- mode parse_dirs(in, out) is semidet.
  parse_dirs([], []).
! parse_dirs([Tok|Toks], Dirs) :-
! 	( Tok = num(Subdir) ->
! 		Dirs = [child(Subdir)|RestDirs],
  		parse_dirs(Toks, RestDirs)
! 	; Tok = (..) ->
! 		Dirs = [parent|RestDirs],
  		parse_dirs(Toks, RestDirs)
  	;
! 		% Forgive almost anything else
  		parse_dirs(Toks, Dirs)
  	).
  
  :- pred parse_setting(list(token), setting).
  :- mode parse_setting(in, out) is semidet.
! parse_setting([Tok|Toks], Setting) :-
  	( Tok = name("depth") ->
  		Toks = [num(Depth)],
  		Setting = depth(Depth)
--- 271,311 ----
  :- mode parse_path(in, out) is semidet.
  	% SICStus is forgiving in the syntax of paths, hence so are we.
  	% XXX: Be less forgiving?
! parse_path([Tok | Toks], Path) :-
  	( Tok = (/) ->
  		Path = root_rel(Dirs),
  		parse_dirs(Toks, Dirs)
  	;
  		Path = dot_rel(Dirs),
! 		parse_dirs([Tok | Toks], Dirs)
  	).
  
  :- pred parse_dirs(list(token), list(dir)).
  :- mode parse_dirs(in, out) is semidet.
  parse_dirs([], []).
! parse_dirs([Tok | Toks], Dirs) :-
! 	(
! 		Tok = num(Subdir),
! 		Dirs = [child(Subdir) | RestDirs],
  		parse_dirs(Toks, RestDirs)
! 	;
! 		Tok = (..),
! 		Dirs = [parent | RestDirs],
  		parse_dirs(Toks, RestDirs)
  	;
! 		% We can effectively ignore slashes (for Unix-style
! 		% pathnames) and carets (for SICStus-style pathnames),
! 		% but anything else is not allowed.
! 		Tok = (/),
! 		parse_dirs(Toks, Dirs)
! 	;
! 		Tok = (^),
  		parse_dirs(Toks, Dirs)
  	).
  
  :- pred parse_setting(list(token), setting).
  :- mode parse_setting(in, out) is semidet.
! parse_setting([Tok | Toks], Setting) :-
  	( Tok = name("depth") ->
  		Toks = [num(Depth)],
  		Setting = depth(Depth)
***************
*** 371,381 ****
  :- mode show_dirs(in, di, uo) is det.
  show_dirs([]) -->
  	io__nl.
! show_dirs([child(Num)|Dirs]) -->
  	io__write_int(Num),
  	io__write_string("/"),
  	show_dirs(Dirs).
! show_dirs([parent|Dirs]) -->
  	io__write_string("../"),
  	show_dirs(Dirs).
  
--- 382,392 ----
  :- mode show_dirs(in, di, uo) is det.
  show_dirs([]) -->
  	io__nl.
! show_dirs([child(Num) | Dirs]) -->
  	io__write_int(Num),
  	io__write_string("/"),
  	show_dirs(Dirs).
! show_dirs([parent | Dirs]) -->
  	io__write_string("../"),
  	show_dirs(Dirs).
  
== util.m =================================================
*** 1.7	1998/10/16 04:23:50
--- util.m	1998/10/16 07:44:50
***************
*** 8,33 ****
  
  :- interface.
  
! :- import_module std_util, string, list.
  
- :- pred util__typename(univ, string).
- :- mode util__typename(in, out) is det.
- 
- :- pred util__functor(univ, string).
- :- mode util__functor(in, out) is det.
- 
- :- pred util__args(univ, list(univ)).
- :- mode util__args(in, out) is det.
- 
- :- pred util__arity(univ, int).
- :- mode util__arity(in, out) is det.
- 
- :- pred util__copy(int, T, list(T)).
- :- mode util__copy(in, in, out) is det.
- 
  :- pred util__zip_with(pred(T1, T2, T3), list(T1), list(T2), list(T3)).
  :- mode util__zip_with(pred(in, in, out) is det, in, in, out) is det.
  
  :- pred util__limit(pred(list(T), list(T)), list(T), list(T)).
  :- mode util__limit(pred(in,out) is det, in, out) is det.
  
--- 8,20 ----
  
  :- interface.
  
! :- import_module list.
  
  :- pred util__zip_with(pred(T1, T2, T3), list(T1), list(T2), list(T3)).
  :- mode util__zip_with(pred(in, in, out) is det, in, in, out) is det.
  
+ 	% Apply predicate to argument repeatedly until the result
+ 	% remains the same.
  :- pred util__limit(pred(list(T), list(T)), list(T), list(T)).
  :- mode util__limit(pred(in,out) is det, in, out) is det.
  
***************
*** 34,64 ****
  %---------------------------------------------------------------------------%
  :- implementation.
  
! :- import_module std_util, list, string, int, require.
  
- 
- util__functor(Univ, Functor) :-
- 	deconstruct(Univ, Functor, _Arity, _Args).
- 	
- util__args(Univ, Args) :-
- 	deconstruct(Univ, _Functor, _Arity, Args).
- 
- util__arity(Univ, Arity) :-
- 	deconstruct(Univ, _Functor, Arity, _Args).
- 	
- util__typename(Univ, TypeName) :-
- 	TypeInfo = univ_type(Univ),
- 	TypeName = type_name(TypeInfo).
- 
- util__copy(N, X, Xs) :-
- 	( N =< 0 ->
- 		Xs = []
- 	;
- 		util__copy(N1, X, Xs2),
- 		Xs = [X|Xs2],
- 		N1 is N - 1
- 	).
- 
  util__zip_with(Pred, XXs, YYs, Zipped) :-
  	( (XXs = [], YYs = []) ->
  		Zipped = []
--- 21,28 ----
  %---------------------------------------------------------------------------%
  :- implementation.
  
! :- import_module list, int, require.
  
  util__zip_with(Pred, XXs, YYs, Zipped) :-
  	( (XXs = [], YYs = []) ->
  		Zipped = []
***************
*** 70,76 ****
  		error("zip_with: list arguments are of unequal length")
  	).
  
- 
  util__limit(Pred, Xs, Ys) :-
  	Pred(Xs, Zs),
  	( Xs = Zs ->
--- 34,39 ----



More information about the developers mailing list