[m-dev.] for review: use readline in the browser

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Tue May 11 17:20:51 AEST 1999


Hi,

This change is motivated by the need to write test cases for the
declarative debugger, prior to enabling it by default.  Test
cases do not currently work when readline is used, because of
problems with redirecting stdin.  The problem is fixed (or atleast
avoided) by using the same method of input for the browser as for
the internal debugger.  I never tracked down the cause of the
problems, so I don't know exactly why this change fixes them, but
it is arguably a better design to have all input going through
one place (MR_trace_getline) anyway.

Similar changes will be made to the declarative debugger when
(and if) this passes review.

This is for review by Zoltan.


Estimated hours taken: 5

Use the same method of input for the browser as for the internal
tracer.  Previously, the browser did input via the Mercury library
and the internal tracer did input via readline (if available).  This
did not work properly if files were redirected into stdin, which meant
that test cases could not be written for the browser.  This change
also adds a test case.

browser/util.m:
	Add a predicate, util__trace_getline/4, which does input via
	the same method used by the internal debugger.

browser/parse.m:
	Call util__trace_getline/4 instead of io__read_line/3.

browser/browse.m:
	Pass the prompt to browser/parse.m as a string, rather than
	printing it before calling.

trace/mercury_trace_internal.c:
trace/mercury_trace_internal.h:
	Declare MR_trace_getline extern.

runtime/mercury_init.h:
runtime/mercury_wrapper.c:
runtime/mercury_wrapper.h:
util/mkinit.c:
	Make MR_trace_getline available to the browser via a function
	pointer.

tests/debugger/Mmakefile:
	Add the new test case.

tests/debugger/browser_test.m:
tests/debugger/browser_test.inp:
tests/debugger/browser_test.exp:
	The new test case.

Index: browser/browse.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/browse.m,v
retrieving revision 1.7
diff -u -r1.7 browse.m
--- browse.m	1999/02/23 22:37:43	1.7
+++ browse.m	1999/05/06 08:25:43
@@ -174,8 +174,8 @@
 :- pred browse_main_loop(browser_state, browser_state, io__state, io__state).
 :- mode browse_main_loop(in, out, di, uo) is det.
 browse_main_loop(State0, State) -->
-	prompt,
-	parse__read_command(Command),
+	{ prompt(Prompt) },
+	parse__read_command(Prompt, Command),
 	( { Command = quit } ->
 		% io__write_string("quitting...\n")
 		{ State = State0 }
@@ -189,9 +189,8 @@
 	io__write_string("-- Simple Mercury Term Browser.\n"),
 	io__write_string("-- Type \"help\" for help.\n\n").
 
-:- pred prompt(io__state::di, io__state::uo) is det.
-prompt -->
-	io__write_string("browser> ").
+:- pred prompt(string::out) is det.
+prompt("browser> ").
 
 
 :- pred run_command(command, browser_state, browser_state,
Index: browser/parse.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/parse.m,v
retrieving revision 1.2
diff -u -r1.2 parse.m
--- parse.m	1999/03/10 20:20:09	1.2
+++ parse.m	1999/05/10 15:35:37
@@ -60,7 +60,7 @@
 
 :- interface.
 
-:- import_module io, list.
+:- import_module io, list, string.
 
 :- type command
 	--->	ls(path)
@@ -99,8 +99,8 @@
 	;	pretty
 	;	verbose.
 
-:- pred parse__read_command(command, io__state, io__state).
-:- mode parse__read_command(out, di, uo) is det.
+:- pred parse__read_command(string, command, io__state, io__state).
+:- mode parse__read_command(in, out, di, uo) is det.
 
 :- pred default_depth(int).
 :- mode default_depth(out) is det.
@@ -108,7 +108,8 @@
 %---------------------------------------------------------------------------%
 :- implementation.
 
-:- import_module io, list, string, char, int, std_util.
+:- import_module char, int, std_util.
+:- import_module util.
 
 
 :- type token
@@ -123,8 +124,8 @@
 	;	unknown(char)
 	.
 
-parse__read_command(Comm) -->
-	io__read_line(Result),
+parse__read_command(Prompt, Comm) -->
+	util__trace_getline(Prompt, Result),
 	( { Result = ok(Cs) } ->
 		{ lexer(Cs, Tokens) },
 		( { parse(Tokens, Comm2) } ->
Index: browser/util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/util.m,v
retrieving revision 1.1
diff -u -r1.1 util.m
--- util.m	1998/10/25 07:16:41	1.1
+++ util.m	1999/05/10 16:18:02
@@ -8,7 +8,13 @@
 
 :- interface.
 
-:- import_module list.
+:- import_module list, string, char, io.
+
+	% Get user input via the same method used by the internal
+	% debugger.
+:- pred util__trace_getline(string, io__result(list(char)), io__state,
+		io__state).
+:- mode util__trace_getline(in, out, di, uo) 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.
@@ -21,7 +27,47 @@
 %---------------------------------------------------------------------------%
 :- implementation.
 
-:- import_module list, int, require.
+:- import_module int, require.
+
+:- pragma promise_pure(util__trace_getline/4).
+
+util__trace_getline(Prompt, Result) -->
+	{
+		impure call_trace_getline(Prompt, Line)
+	->
+		string__to_char_list(Line, Chars),
+		Result = ok(Chars)
+	;
+		Result = eof
+	}.
+
+:- impure pred call_trace_getline(string, string).
+:-        mode call_trace_getline(in, out) is semidet.
+
+:- pragma c_header_code("
+	#include ""mercury_wrapper.h""
+	#include ""mercury_string.h""
+	#include ""mercury_trace_internal.h""
+").
+
+:- pragma c_code(call_trace_getline(Prompt::in, Line::out),
+	[will_not_call_mercury],
+	"
+		char		*line;
+		char		*mercury_string;
+
+		line = MR_address_of_trace_getline((char *)Prompt);
+
+		if (line == NULL) {
+			SUCCESS_INDICATOR = FALSE;
+		} else {
+			make_aligned_string_copy(mercury_string, line);
+			free(line);
+			Line = (String) mercury_string;
+			SUCCESS_INDICATOR = TRUE;
+		}
+	"
+).
 
 util__zip_with(Pred, XXs, YYs, Zipped) :-
 	( (XXs = [], YYs = []) ->
Index: runtime/mercury_init.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_init.h,v
retrieving revision 1.12
diff -u -r1.12 mercury_init.h
--- mercury_init.h	1999/04/20 11:48:14	1.12
+++ mercury_init.h	1999/05/10 15:31:08
@@ -117,6 +117,9 @@
 extern	void	ML_io_print_to_cur_stream(Word, Word);
 extern	void	ML_io_print_to_stream(Word, Word, Word);
 
+/* in trace/mercury_trace_internal.h */
+extern	char	*MR_trace_getline(const char *);
+
 /* in trace/mercury_trace_declarative.h */
 extern	void	MR_edt_root_node(Word EDT, Word *Node);
 
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.38
diff -u -r1.38 mercury_wrapper.c
--- mercury_wrapper.c	1999/04/30 06:21:28	1.38
+++ mercury_wrapper.c	1999/05/10 16:06:00
@@ -138,6 +138,8 @@
 void	(*address_of_mercury_init_io)(void);
 void	(*address_of_init_modules)(void);
 
+char *	(*MR_address_of_trace_getline)(const char *);
+
 #ifdef	MR_USE_EXTERNAL_DEBUGGER
 void	(*MR_address_of_trace_init_external)(void);
 void	(*MR_address_of_trace_final_external)(void);
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.19
diff -u -r1.19 mercury_wrapper.h
--- mercury_wrapper.h	1999/04/20 11:48:17	1.19
+++ mercury_wrapper.h	1999/05/10 15:30:22
@@ -62,6 +62,14 @@
 #endif
 
 /*
+** MR_trace_getline(const char *) is defined in trace/mercury_trace_internal.c
+** but is called in browser/util.m.  As we cannot do direct calls from
+** browser/ to trace/, we do an indirect call via the following pointer.
+*/
+
+extern	char *		(*MR_address_of_trace_getline)(const char *);
+
+/*
 ** MR_trace_init_external() and MR_trace_final_external() are defined 
 ** in trace/mercury_trace_external.c but are called in
 ** runtime/mercury_trace_base.c. As we can not do direct calls from
Index: tests/debugger/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.23
diff -u -r1.23 Mmakefile
--- Mmakefile	1999/04/16 01:12:54	1.23
+++ Mmakefile	1999/05/10 12:18:28
@@ -17,6 +17,7 @@
 #-----------------------------------------------------------------------------#
 
 DEBUGGER_PROGS=	\
+	browser_test			\
 	debugger_regs			\
 	existential_type_classes	\
 	implied_instance		\
@@ -56,6 +57,9 @@
 endif
 
 #-----------------------------------------------------------------------------#
+
+browser_test.out: browser_test browser_test.inp
+	$(MDB) ./browser_test < browser_test.inp > browser_test.out 2>&1
 
 debugger_regs.out: debugger_regs debugger_regs.inp
 	$(MDB) ./debugger_regs < debugger_regs.inp > debugger_regs.out 2>&1
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.41
diff -u -r1.41 mercury_trace_internal.c
--- mercury_trace_internal.c	1999/05/06 04:19:21	1.41
+++ mercury_trace_internal.c	1999/05/10 15:26:22
@@ -204,7 +204,6 @@
 			int *word_max, int *word_count);
 static	bool	MR_trace_source(const char *filename);
 static	void	MR_trace_source_from_open_file(FILE *fp);
-static	char	*MR_trace_getline(const char *prompt);
 static	char	*MR_trace_getline_queue(void);
 static	void	MR_insert_line_at_head(const char *line);
 static	void	MR_insert_line_at_tail(const char *line);
@@ -2225,7 +2224,7 @@
 ** occurs on an empty line, return NULL.
 */
 
-static char *
+char *
 MR_trace_getline(const char *prompt)
 {
 	char	*line;
Index: trace/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_trace_internal.h
--- mercury_trace_internal.h	1999/02/20 06:08:19	1.6
+++ mercury_trace_internal.h	1999/05/10 15:26:32
@@ -55,4 +55,6 @@
 extern FILE *MR_mdb_out;
 extern FILE *MR_mdb_err;
 
+extern	char	*MR_trace_getline(const char *prompt);
+
 #endif	/* MERCURY_TRACE_INTERNAL_H */
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.49
diff -u -r1.49 mkinit.c
--- mkinit.c	1999/04/19 08:29:05	1.49
+++ mkinit.c	1999/05/10 15:31:50
@@ -152,6 +152,11 @@
 	"	MR_io_stderr_stream = ML_io_stderr_stream;\n"
 	"	MR_io_print_to_cur_stream = ML_io_print_to_cur_stream;\n"
 	"	MR_io_print_to_stream = ML_io_print_to_stream;\n"
+	"#if MR_TRACE_ENABLED\n"
+	"	MR_address_of_trace_getline = MR_trace_getline;\n"
+	"#else\n"
+	"	MR_address_of_trace_getline = NULL;\n"
+	"#endif\n"
 	"#ifdef MR_USE_EXTERNAL_DEBUGGER\n"
 	"  #if MR_TRACE_ENABLED\n"
 	"	MR_address_of_trace_init_external = MR_trace_init_external;\n"


New module tests/debugger/browser_test.m:

:- module browser_test.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.

:- type big
	--->	big(big, int, big)
	;	small.

main -->
	{ big_data(Data) },
	io__print(Data),
	io__write_string(".\n").

:- pred big_data(big::out) is det.

big_data(Data) :-
	Data = big(
		big(
			big(
				small,
				1,
				small
			),
			2,
			small
		),
		3,
		big(
			big(
				small,
				4,
				big(
					small,
					5,
					small
				)
			),
			6,
			small
		)
	).


New file tests/debugger/browser_test.inp:

echo on
goto 3
print *
browse 0
print
quit
browse HeadVar__1
ls
cd /1
ls
cd /1/2
ls
cd /3
ls
cd 1/3/2
ls
cd
ls
quit
retry
continue -a


New file tests/debugger/browser_test.exp:

       1:      1  1 CALL pred browser_test:main/2-0 (det) 
mdb> echo on
Command echo enabled.
mdb> goto 3
       3:      2  2 EXIT pred browser_test:big_data/1-0 (det) 
mdb> print *
       HeadVar__1           		big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
mdb> browse 0
browser> print
big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
browser> quit
mdb> browse HeadVar__1
browser> ls
big
1-big
| 1-big
| | 1-small
| | 2-1
| | 3-small
| 2-2
| 3-small
2-3
3-big
  1-big
  | 1-small
  | 2-4
  | 3-big/3
  2-6
  3-small

browser> cd /1
browser> ls
big
1-big
| 1-small
| 2-1
| 3-small
2-2
3-small

browser> cd /1/2
browser> ls
2

browser> cd /3
browser> ls
big
1-big
| 1-small
| 2-4
| 3-big
|   1-small
|   2-5
|   3-small
2-6
3-small

browser> cd 1/3/2
browser> ls
5

browser> cd
browser> ls
big
1-big
| 1-big
| | 1-small
| | 2-1
| | 3-small
| 2-2
| 3-small
2-3
3-big
  1-big
  | 1-small
  | 2-4
  | 3-big/3
  2-6
  3-small

browser> quit
mdb> retry
       2:      2  2 CALL pred browser_test:big_data/1-0 (det) 
mdb> continue -a
       3:      2  2 EXIT pred browser_test:big_data/1-0 (det) 
big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big(small, 5, small)), 6, small)).
       4:      1  1 EXIT pred browser_test:main/2-0 (det) 


-- 
Mark Brown  (dougl at cs.mu.oz.au)       )O+   |  For Microsoft to win,
MEngSc student,                             |  the customer must lose
Dept of Computer Science, Melbourne Uni     |          -- Eric S. Raymond
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list