[m-dev.] For review interactive queries for the external debugger
Erwan Jahier
Erwan.Jahier at irisa.fr
Thu Apr 22 01:38:24 AEST 1999
I have appended the corresponding Opium-M code at the end of the diff.
------------------------
Estimated hours taken: 10
This change allows interactive queries to be typed from the external debugger.
browser/debugger_interface.m:
Define new debugger requests: query/1, cc_query/1, io_query/1 and
mmc_options/1.
Define 2 new procedures that are used in trace/mercury_trace_external.c:
get_list_modules_to_import/3 retrieves from a *query/1 request a list
of modules to be imported; and get_mmc_options/2 retrieves from a
mmc_options/1 request the option to pass to mmc to compile the query.
browser/interactive_query.m:
Define a new procedure query_external/7 that does the same job as
query/7 but for the external debugger.
Unset the environment variable `MERCURY_OPTIONS' before compiling a
query; `MERCURY_OPTIONS' is exported before executing a program under
the control of Opium-M (and mdb) and is not supposed to be set before
compiling a program.
trace/mercury_trace_browse.ch:
Add a new function MR_trace_query_external() to interface the
ML_query_external() function defined by browser/interfactive_query.m.
trace/mercury_trace_external.c:
Add code to implement new commands `query', `cc_query', `io_query',
and `mmc_options', using the MR_trace_query_external() function defined
by trace/mercury_trace_browse.h.
trace/mercury_trace_external.h:
Export MR_debugger_socket_in and MR_debugger_socket_out since there
are needed in interactive_query.m.
Index: browser/debugger_interface.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/debugger_interface.m,v
retrieving revision 1.8
diff -u -r1.8 debugger_interface.m
--- debugger_interface.m 1999/02/22 08:28:30 1.8
+++ debugger_interface.m 1999/04/21 14:48:50
@@ -32,6 +32,7 @@
:- implementation.
:- import_module io, require.
:- import_module list, bool, std_util.
+:- import_module interactive_query.
dummy_pred_to_avoid_warning_about_nothing_exported.
@@ -160,6 +161,14 @@
% something went wrong when trying to get the
% next request
; error(string)
+ % to type interactive queries
+ ; query(imports)
+ % to type cc interactive queries
+ ; cc_query(imports)
+ % to type interactive queries that perform io
+ ; io_query(imports)
+ % options to compile queries with
+ ; mmc_options(options)
.
:- type event_number == int.
@@ -513,6 +522,60 @@
***********/
+%-----------------------------------------------------------------------------%
+
+:- pred get_list_modules_to_import(debugger_request, int, imports).
+:- mode get_list_modules_to_import(in, out, out) is det.
+
+:- pragma export(get_list_modules_to_import(in, out, out),
+ "ML_DI_get_list_modules_to_import").
+
+get_list_modules_to_import(DebuggerRequest, CardList, ModulesList) :-
+ (
+ DebuggerRequest = query(List)
+ ->
+ ModulesList = List,
+ length(ModulesList, CardList)
+ ;
+ DebuggerRequest = cc_query(List)
+ ->
+ ModulesList = List,
+ length(ModulesList, CardList)
+ ;
+ DebuggerRequest = io_query(List)
+ ->
+ ModulesList = List,
+ length(ModulesList, CardList)
+ ;
+ error("get_list_modules_to_import: not a query request")
+ ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred get_mmc_options(debugger_request, options).
+:- mode get_mmc_options(in, out) is det.
+
+:- pragma export(get_mmc_options(in, out), "ML_DI_get_mmc_options").
+
+get_mmc_options(DebuggerRequest, Options) :-
+ (
+ DebuggerRequest = mmc_options(Options1)
+ ->
+ Options = Options1
+ ;
+ error("get_mmc_options: not a mmc_options request")
+ ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred init_mercury_string(string).
+:- mode init_mercury_string(out) is det.
+
+:- pragma export(init_mercury_string(out), "ML_DI_init_mercury_string").
+
+init_mercury_string("").
+
+%------------------------------------------------------------------------------%
:- pred classify_request(debugger_request, int).
:- mode classify_request(in, out) is det.
@@ -533,6 +596,10 @@
classify_request(stack, 10).
classify_request(nondet_stack, 11).
classify_request(stack_regs, 12).
+classify_request(query(_),13).
+classify_request(cc_query(_),14).
+classify_request(io_query(_),15).
+classify_request(mmc_options(_),16).
%-----------------------------------------------------------------------------%
Index: browser/interactive_query.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/interactive_query.m,v
retrieving revision 1.2
diff -u -r1.2 interactive_query.m
--- interactive_query.m 1999/03/25 22:24:51 1.2
+++ interactive_query.m 1999/04/21 14:48:51
@@ -22,6 +22,10 @@
io__input_stream::in, io__output_stream::in,
state::di, state::uo) is det.
+% query_external/7 is the same as query/7 but for the use of the external
+% debugger.
+:- pred query_external(query_type::in, imports::in, options::in,
+ io__input_stream::in, io__output_stream::in,
+ state::di, state::uo) is det.
+
:- type query_type ---> normal_query ; cc_query ; io_query.
:- type imports == list(string).
:- type options == string.
@@ -73,6 +77,62 @@
)
).
+
+% Type of the terms sent to the socket during an interactive query session
+% under the control of the external debugger.
+:- type interactive_query_response
+ ---> iq_ok
+ ; iq_imported(imports)
+ ; iq_quit
+ ; iq_eof
+ ; iq_error(string)
+ .
+
+:- pragma export(query_external(in, in, in, in, in, di, uo),
+ "ML_query_external").
+
+query_external(QueryType, Imports, Options, SocketIn, SocketOut) -->
+ io__set_input_stream(SocketIn, OldStdin),
+ term_io__read_term(Result),
+ io__set_input_stream(OldStdin, _),
+ ( { Result = eof },
+ send_term_to_socket(iq_eof, SocketOut)
+ ; { Result = error(ErrorMsg, _Line) },
+ send_term_to_socket(iq_error(ErrorMsg), SocketOut),
+ query_external(QueryType, Imports, Options, SocketIn, SocketOut)
+ ; { Result = term(VarSet, Term) },
+ (if { Term = term__functor(term__atom("quit"), [], _) } then
+ send_term_to_socket(iq_quit, SocketOut)
+ else if { Term = term__functor(term__atom("options"),
+ [term__functor(term__string(NewOptions),
+ [], _)], _) } then
+ send_term_to_socket(iq_ok, SocketOut),
+ query_external(QueryType, Imports, NewOptions,
+ SocketIn, SocketOut)
+ else if { term_to_list(Term, ModuleList) } then
+ { list__append(Imports, ModuleList, NewImports) },
+ send_term_to_socket(iq_imported(NewImports), SocketOut),
+ query_external(QueryType, NewImports, Options,
+ SocketIn, SocketOut)
+ else
+ run_query(Options,
+ prog(QueryType, Imports, Term, VarSet)),
+ send_term_to_socket(iq_ok, SocketOut),
+ query_external(QueryType, Imports, Options,
+ SocketIn, SocketOut)
+ )
+ ).
+
+:- pred send_term_to_socket(interactive_query_response, io__output_stream,
+ io__state, io__state).
+:- mode send_term_to_socket(in, in, di, uo) is det.
+send_term_to_socket(Term, SocketStream) -->
+ write(SocketStream, Term),
+ print(SocketStream, ".\n"),
+ flush_output(SocketStream).
+
:- func query_prompt(query_type) = string.
query_prompt(normal_query) = "?- ".
query_prompt(cc_query) = "?- ".
@@ -90,12 +150,19 @@
:- mode run_query(in, in, di, uo) is det.
run_query(Options, Program) -->
{ SourceFile = "query.m" },
- write_prog_to_file(Program, SourceFile),
- compile_file(Options, Succeeded),
- (if { Succeeded = yes } then
- dynamically_load_and_run
+ io__get_environment_var("MERCURY_OPTIONS", MAYBE_MERCURY_OPTIONS),
+ (if { MAYBE_MERCURY_OPTIONS = yes(MERCURY_OPTIONS) } then
+ io__set_environment_var("MERCURY_OPTIONS", ""),
+ write_prog_to_file(Program, SourceFile),
+ compile_file(Options, Succeeded),
+ (if { Succeeded = yes } then
+ dynamically_load_and_run
+ else
+ { true }
+ ),
+ io__set_environment_var("MERCURY_OPTIONS", MERCURY_OPTIONS)
else
- { true }
+ print("Unable to unset MERCURY_OPTIONS environment variable")
).
%-----------------------------------------------------------------------------%
Index: trace/mercury_trace_browse.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_trace_browse.c
--- mercury_trace_browse.c 1999/03/05 12:52:33 1.3
+++ mercury_trace_browse.c 1999/04/21 14:48:55
@@ -29,6 +29,7 @@
#include "browse.h"
#include "interactive_query.h"
#include "std_util.h"
+#include "mercury_trace_external.h"
#include <stdio.h>
static Word MR_trace_browser_state;
@@ -129,5 +130,16 @@
MR_TRACE_CALL_MERCURY(
ML_query(type, imports_list, (String) options_on_heap,
(Word) &mdb_in, (Word) &mdb_out);
+ );
+}
+
+void
+MR_trace_query_external(MR_Query_Type type, String options, int num_imports,
+ Word imports_list)
+{
+ MR_TRACE_CALL_MERCURY(
+ ML_query_external(type, imports_list, options,
+ (Word) &MR_debugger_socket_in,
+ (Word) &MR_debugger_socket_out);
);
}
Index: trace/mercury_trace_browse.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_browse.h
--- mercury_trace_browse.h 1999/03/05 12:52:33 1.2
+++ mercury_trace_browse.h 1999/04/21 14:48:55
@@ -35,4 +35,7 @@
extern void MR_trace_query(MR_Query_Type type, const char *options,
int num_imports, /* const */ char *imports[]);
+extern void MR_trace_query_external(MR_Query_Type type, String options,
+ int num_imports, Word imports_list);
+
#endif /* MERCURY_TRACE_BROWSE_H */
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.14
diff -u -r1.14 mercury_trace_external.c
--- mercury_trace_external.c 1999/03/25 03:02:18 1.14
+++ mercury_trace_external.c 1999/04/21 14:48:57
@@ -27,6 +27,7 @@
#include "mercury_trace_external.h"
#include "mercury_trace_util.h"
#include "mercury_layout_util.h"
+#include "mercury_trace_browse.h"
#include "debugger_interface.h"
#include "std_util.h"
@@ -65,13 +66,21 @@
port of the current event */
MR_REQUEST_STACK = 10,/* print the ancestors list */
MR_REQUEST_NONDET_STACK = 11,/* print the nondet stack */
- MR_REQUEST_STACK_REGS = 12 /* prints the contents of the virtual
+ MR_REQUEST_STACK_REGS = 12,/* prints the contents of the virtual
machine registers. */
+ MR_REQUEST_INTERACTIVE_QUERY_NORMAL
+ = 13,/* wait for a normal interactive query */
+ MR_REQUEST_INTERACTIVE_QUERY_CC
+ = 14,/* wait for a cc interactive query */
+ MR_REQUEST_INTERACTIVE_QUERY_IO
+ = 15,/* wait for a io interactive query */
+ MR_REQUEST_MMC_OPTIONS = 16 /* import modules for interactive
+ queries */
} MR_debugger_request_type;
-static MercuryFile MR_debugger_socket_in;
-static MercuryFile MR_debugger_socket_out;
+MercuryFile MR_debugger_socket_in;
+MercuryFile MR_debugger_socket_out;
/*
** Use a GNU C extension to enforce static type checking
@@ -116,6 +125,10 @@
static void MR_dump_stack_record_print_to_socket(FILE *fp,
const MR_Stack_Layout_Entry *entry_layout, int count,
int start_level, Word *base_sp, Word *base_curfr);
+static void MR_get_list_modules_to_import(Word debugger_request,
+ Integer *modules_list_card_ptr, Word *modules_list_ptr);
+static void MR_get_mmc_options(Word debugger_request,
+ String *mmc_options_ptr);
#if 0
This pseudocode should go in the debugger process:
@@ -375,7 +388,16 @@
MR_Trace_Port port = event_info->MR_trace_port;
const char *path = event_info->MR_event_path;
Word *saved_regs = event_info->MR_saved_regs;
+ Integer modules_list_card;
+ Word modules_list;
+/*
+** MR_mmc_options contains the options to pass to mmc when compiling queries.
+** We initialise it to the String "".
+*/
+ static String MR_mmc_options;
+ MR_TRACE_CALL_MERCURY(ML_DI_init_mercury_string(&MR_mmc_options));
+
event_details.MR_call_seqno = MR_trace_call_seqno;
event_details.MR_call_depth = MR_trace_call_depth;
event_details.MR_event_number = MR_trace_event_number;
@@ -533,6 +555,56 @@
MR_saved_maxfr(saved_regs));
break;
+ case MR_REQUEST_INTERACTIVE_QUERY_NORMAL:
+ if (MR_debug_socket) {
+ fprintf(stderr, "\nMercury runtime: "
+ "REQUEST_INTERACTIVE_QUERY"
+ "_NORMAL\n");
+ }
+ MR_get_list_modules_to_import(
+ debugger_request, &modules_list_card,
+ &modules_list);
+ MR_trace_query_external(MR_NORMAL_QUERY,
+ MR_mmc_options, modules_list_card,
+ modules_list);
+ break;
+
+ case MR_REQUEST_INTERACTIVE_QUERY_IO:
+ if (MR_debug_socket) {
+ fprintf(stderr, "\nMercury runtime: "
+ "REQUEST_INTERACTIVE_QUERY_IO\n");
+ }
+ MR_get_list_modules_to_import(
+ debugger_request, &modules_list_card,
+ &modules_list);
+ MR_trace_query_external(MR_IO_QUERY,
+ MR_mmc_options, modules_list_card,
+ modules_list);
+ break;
+
+ case MR_REQUEST_INTERACTIVE_QUERY_CC:
+ if (MR_debug_socket) {
+ fprintf(stderr, "\nMercury runtime: "
+ "REQUEST_INTERACTIVE_QUERY_CC\n");
+ }
+ MR_get_list_modules_to_import(
+ debugger_request, &modules_list_card,
+ &modules_list);
+ MR_trace_query_external(MR_CC_QUERY,
+ MR_mmc_options, modules_list_card,
+ modules_list);
+ break;
+
+ case MR_REQUEST_MMC_OPTIONS:
+ if (MR_debug_socket) {
+ fprintf(stderr, "\nMercury runtime: "
+ "REQUEST_MMC_OPTIONS\n");
+ }
+ MR_get_mmc_options(debugger_request,
+ &MR_mmc_options);
+ MR_send_message_to_socket("mmc_options_ok");
+ break;
+
case MR_REQUEST_NO_TRACE:
cmd->MR_trace_cmd = MR_CMD_TO_END;
return jumpaddr;
@@ -1057,6 +1129,28 @@
MR_send_message_to_socket_format("det(\"%s\").\n",
MR_detism_names[entry->MR_sle_detism]);
+}
+
+static void
+MR_get_list_modules_to_import(Word debugger_request,
+ Integer *modules_list_card_ptr, Word *modules_list_ptr)
+{
+ MR_TRACE_CALL_MERCURY(
+ ML_DI_get_list_modules_to_import(
+ debugger_request,
+ modules_list_card_ptr,
+ modules_list_ptr);
+ );
+}
+
+static void
+MR_get_mmc_options(Word debugger_request, String *mmc_options_ptr)
+{
+ MR_TRACE_CALL_MERCURY(
+ ML_DI_get_mmc_options(
+ debugger_request,
+ mmc_options_ptr);
+ );
}
#endif /* MR_USE_EXTERNAL_DEBUGGER */
Index: trace/mercury_trace_external.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_trace_external.h
--- mercury_trace_external.h 1999/02/20 06:08:14 1.5
+++ mercury_trace_external.h 1999/04/21 14:48:57
@@ -14,6 +14,13 @@
extern Code *MR_trace_event_external(MR_Trace_Cmd_Info *cmd,
MR_Event_Info *event_info);
+/*
+** External debugger socket streams.
+*/
+
+extern MercuryFile MR_debugger_socket_in;
+extern MercuryFile MR_debugger_socket_out;
+
#endif /* MR_USE_EXTERNAL_DEBUGGER */
#endif /* MERCURY_TRACE_EXTERNAL_H */
%------------------------------------------------------------------------------%
% Copyright (C) 1999 IRISA/INRIA.
%
% Author : Erwan Jahier
% File : interactive_queries.op
%
%------------------------------------------------------------------------------%
opium_scenario(
name : interactive_queries,
files : [interactive_queries],
scenarios : [],
message :
"Scenario that handles interactive queries."
).
%------------------------------------------------------------------------------%
opium_command(
name : query,
arg_list : [ModuleList],
arg_type_list : [is_list],
abbrev : _,
interface : menu,
command_type : opium,
implementation : query_Op,
parameters : [],
message :
"The commands query/1, cc_query/1 and io_query/1 allow you to type in queries \
(goals) interactively in the debugger. When you use one of these commands, the \
debugger will respond with a query prompt (`?-' or `run <--'), at which you \
can type in a goal; the debugger will the compile and execute the goal and \
display the answer(s). You can return from the query prompt to the Opium-M \
prompt by typing the end-of-file indicator (typically control-D or \
control-Z), or by typing `quit.'. \n\
\n\
The list of module names passed downed in argument of the query specify which \
modules will be imported. Note that you can also add new modules to the list \
of imports directly at the query prompt, by using a command of the form \
`[\"module\"]', e.g. `[\"int\"]'. You need to import all the modules that \
define symbols used in your query. Queries can only use symbols that are \
exported from a module; entities which are declared in a module's \
implementation section only cannot be used. \n\
\n\
The three variants differ in what kind of goals they allow. For goals which \
perform I/O, you need to use `io_query/1'; this lets you type in the goal \
using DCG syntax. For goals which don't do I/O, but which have determinism \
`cc_nondet' or `cc_multi', you need to use `cc_query/1'; this finds only one \
solution to the specified goal. For all other goals, you can use plain \
`query/1', which finds all the solutions to the goal. \
\n\
For `query/1' and `cc_query/1', the debugger will print out all the variables \
in the goal using `io__write'. The goal must bind all of its variables to \
ground terms, otherwise you will get a mode error. \n\
\n\
The current implementation works by compiling the queries on-the-fly and then \
dynamically linking them into the program being debugged. Thus it may take a \
little while for your query to be executed. Each query will be written to a \
file named `query.m' in the current directory, so make sure you don't name \
your source file `query.m'. Note that dynamic linking may not be supported \
on some systems; if you are using a system for which dynamic linking is not \
supported, you will get an error message when you try to run these commands."
).
query_Op(ModuleList) :-
( not getval(state_of_opium, running) ->
write("No program is running, you can't make a query.\n")
;
true
),
% strings need to quoted before being sent.
maplist(quote_string, ModuleList, QuotedList),
send_message_to_socket(query(QuotedList)),
loop_for_queries(query).
loop_for_queries(QueryType) :-
display_query_prompt(QueryType),
read(Term),
( Term = options(String) ->
quote_string(String, QuotedString),
Term2 = options(QuotedString)
;
Term2 = Term
),
send_message_to_socket(Term2),
nl,
read_message_from_socket(Response),
(
( Response == iq_eof ; Response == iq_quit ),
write("End of the interactive queries session.\n"),
!
;
Response = iq_imported(ImportedMod),
write("The currently imported modules are "),
print(ImportedMod),
nl,
loop_for_queries(QueryType),
!
;
Response = iq_error(ErrorMsg),
printf("%w\n", ErrorMsg),
loop_for_queries(QueryType),
!
;
Response == iq_ok,
nl,
loop_for_queries(QueryType),
!
;
% Should never occur
printf("Bad message from interactive_query:query_", []),
printf("external/7: %w.\n", Response),
fail
).
display_query_prompt(query) :-
write("\n?- ").
display_query_prompt(cc_query) :-
write("\n?- ").
display_query_prompt(io_query) :-
write("\nrun <-- ").
quote_string(String, StringQuoted):-
concat_string(["\"", String, "\""], String2),
atom_string(StringQuoted, String2).
%------------------------------------------------------------------------------%
opium_command(
name : cc_query,
arg_list : [ModuleList],
arg_type_list : [is_list],
abbrev : _,
interface : menu,
command_type : opium,
implementation : cc_query_Op,
parameters : [],
message :
"cf query/1."
).
cc_query_Op(ModuleList) :-
( not getval(state_of_opium, running) ->
write("No program is running, you can't make a query.\n")
;
true
),
% strings need to quoted before being sent.
maplist(quote_string, ModuleList, QuotedList),
send_message_to_socket(cc_query(QuotedList)),
loop_for_queries(cc_query).
%------------------------------------------------------------------------------%
opium_command(
name : io_query,
arg_list : [ModuleList],
arg_type_list : [is_list],
abbrev : _,
interface : menu,
command_type : opium,
implementation : io_query_Op,
parameters : [],
message :
"cf query/1."
).
io_query_Op(ModuleList) :-
( not getval(state_of_opium, running) ->
write("No program is running, you can't make a query.\n")
;
true
),
% strings need to quoted before being sent.
maplist(quote_string, ModuleList, QuotedList),
send_message_to_socket(io_query(QuotedList)),
loop_for_queries(io_query).
%------------------------------------------------------------------------------%
opium_command(
name : mmc_options,
arg_list : [String],
arg_type_list : [string],
abbrev : _,
interface : menu,
command_type : opium,
implementation : mmc_options_Op,
parameters : [],
message :
"This command sets the options that will be passed to `mmc' to compile your \
query when you use one of the query commands: `query/1', `cc_query/2', or \
`io_query/3'. For example, if a query results in a compile error, it may \
sometimes be helpful to use mmc_options(\"mmc_options --verbose-errors\").\
"
).
mmc_options_Op(Options) :-
( not getval(state_of_opium, running) ->
write("No program is running, you can't set mmc options.\n")
;
true
),
quote_string(Options, QuotedOptions),
send_message_to_socket(mmc_options(QuotedOptions)),
read_message_from_socket(Response),
printf("response to query = %w\n", [Response]),
(
Response == mmc_options_ok,
nl
;
% Should never occur
write("Bad message from the Mercury proccess.\n"),
write("mmc_options_ok expected.\n"),
fail
).
--
R1.
--------------------------------------------------------------------------
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