[m-dev.] collect

Erwan Jahier Erwan.Jahier at irisa.fr
Fri Jun 25 03:29:55 AEST 1999


Fergus wrote:
| On 11-Jun-1999, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
| > The main advantages of this approach are :
| > - the simplicity of use (any user can get the monitor he needs),
| > - the flexibility,
| > - the synergy between tools.
| > 
| > The main drawback is of course efficiency due in particular to socket traffic
| > and context switches between the debugger and the debuggee.
| 
| Another drawback is the need for the user to learn two languages:
| as well as knowing Mercury, they also need to learn the Prolog-based
| Opium-M command language.

Well, Ok but:

1) Opium-M command language is nothing more than Prolog + 2 primitives that
manipulate the trace (current/1 and fget/1), which is not such a big step for
Mercury programmers.

2) End-users don't need to know Prolog to use Opium-M the same way as they
don't need to know Lisp to use emacs. If anyone wants to extend the set of
functionalities of Opium-M, then yes he needs to learn about Prolog as he need
to learn Lisp if he wants to write a new macro for emacs.

3) Opium (for Prolog) and Coca (for C) uses the same language as it is possible
to edit various kinds of programs within emacs. This is very nice because for
example, when students here are implementing a GUI for Coca, it is possible to
use it for Opium-M.


We strongly think that a Prolog interpreter is the most suitable to type
queries on the fly. Of course, when writing Opium-M commands that are real
programs, then being able to write it in Mercury would be very nice, but it 
would lead to something a bit heterogeneous.

Of cource, if we had a Mercury commands interpreter that is as convenient as
the eclipse one to type queries on the fly, then things would be quite
different and Mercury might be the best candidate for the 3 debuggers. But I am
not convinced the Mercury semantics will let you get that.

| > The `collect' is described in more details in a article that I submitted 
| > recently and that is available at:
| > http://www.irisa.fr/EXTERNE/projet/lande/jahier/collect.ps
| 
| This looks like it could be a very elegant approach!
| 
| I'd like to see something along these lines become part of the standard
| Mercury distribution.

Great!
I would be delighted to do that.
 
| The paper skimmed over a few things -- I'd like to know more of the details.
| For example, the interface to `collect' is not entirely clear -- what are
| the types of the arguments?

Do you mean the type `event' ? (the only other argument type is collected_type 
which defined by users so...)

The type event is defined the following way :

:- type event ---> 
	event(  event_number,
		call_number,
		depth_number,
		trace_port_type,
		pred_or_func,
		string,		% declaration module name
		string,		% definition module name
		proc_name,		% pred name
		arity,
		mode_num,
		determinism,
		goal_path_string).

You will soon be able to get a few more details since I am about to submit a 
diff that implements what is described in the paper.
 
| It might be more elegant if the dynamically linked module defined a single
| function returning an instance of a standard typeclass, rather than defining
| a type and two specific predicates acting on that type, with specific
| argument types, modes and determinism.  

The 2 predicates always have the same type, mode and determinim i.e.:

:- pred initialize(collected_type::out) is det.
:- pred filter(event::in, collected_type::in, collected_type::out) is det.

The only things the user needs to write is:
- the type of the collecting variable
- the body of initialize/1 
- the body of filter/3

Note that I could have let the collecting variable uninstanciated:

:- pred initialize(T) .
:- pred filter(event, T, T).

But I didn't do that for performance reasons; I thought I would pay the price
of the polymorphism. On a second thought, I may be wrong about that and maybe
the compiler is able to optimize that away after all. Is it? 

| This would of course require
| existential types ;)  The interface would then always look like this
| 
| 	:- module foo.
| 	:- interface.
| 	:- import_module collect.
| 
| 	:- some [T] func make_collector = T => collector(T).
| 
| and the implementation would look something like this
| 
| 	:- implementation.
| 
| 	% this one just counts the number of events
| 
| 	:- type state ---> state(int). % or whatever
| 
| 	make_collector = state(0).
| 
| 	:- instance collector(state) where [pred(filter/3) is do_filter].
| 
| 	do_filter(_Event, state(N), state(N+1)).

In which sense do you say it is more elegant?

| Also, it might be a good idea to make `filter' also return a bool
| which says whether to keep on going -- some filters need not examine
| the whole trace.

Yes, that 's a good idea.
 
| This kind of approach could also be extended to provide features like
| conditional breakpoints in the internal debugger.

Certainly. Note that this proposal does not rely on Opium-M in any ways.


-- 
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