%------------------------------------------------------------------------------% % Copyright (C) 1999 INRIA/INSA de Rennes. % This file may only be copied under the terms of the GNU Library General % Public License - see the file License in the Morphine distribution. % % 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 Morphine \ 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 down in the 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." ). % Most of this documentation is duplicated from the documentation % in mercury/doc/user_guide.texi. query_Op(ModuleList) :- any_query(ModuleList, query). any_query(ModuleList, QueryType) :- ( not getval(state_of_morphine, 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), Message =.. [QueryType, QuotedList], send_message_to_socket(Message), loop_for_queries(QueryType). 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), get_parameter(debug_morphine, OnOff), ( OnOff == on -> printf("response to query = %w\n", [Response]) ; true ), ( ( 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) :- any_query(ModuleList, 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) :- any_query(ModuleList, 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(\"--verbose-errors\").\ " ). mmc_options_Op(Options) :- ( not getval(state_of_morphine, 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 == response_mmc_option_ok, nl ; % Should never occur write("Bad message from the Mercury proccess.\n"), write("mmc_option_ok expected.\n"), fail ).