next up previous contents index
Next: Scenario ``control_flow'' Up: Morphine - Reference Manual Previous: Scenario ``step_by_step''

Subsections

     
Scenario ``collect''

Scenario that implements the collect/2 monitoring command that collects runtime information from Mercury program executions. It is intended to let users easily implement their own monitors with acceptable performances.

To use it, users just need to define 4 things in a file, using the Mercury syntax:

1.
a `collected_type' which is the type of the collecting variable that will contain the result of the monitoring activity.
2.
The predicate initialize/1 which initializes this collecting variable. initialize/1 should follow the following declarations:
		
	:- pred initialize(collected_type).
	:- mode initialize(out) is det.

3.
The predicate filter/4 which updates the collecting variable at each execution event. filter/4 also outputs a variable that indicates whether to stop collecting. If this variable is set to `stop', the collect process stops; if it is set to `continue', it continues. If this variable is always set to `continue', the collecting will process until the last event is reached. filter/4 should follow the following declarations:
		
	:- pred filter(event, collected_type, collected_type, 
		stop_or_continue).
	:- mode filter(in, acc_in, acc_out, out) is det.

where `acc_in' and `acc_out' have `in' and `out' respectively as default values.

4.
And optionally the mode definition of `acc_in' and `acc_out' in one want to override their default values.

The event type is defined as follows (for more detail about the meaning of each event attributes, please refer to the Reference Manual):


:- type event -->
event(
event_number,
call_number,
depth_number,
trace_port_type,
pred_or_func,
declarated_module_name,
defined_module_name,
proc_name,
arity,
mode_number,
determinism,
goal_path_string).


:- type event_number == int.
:- type call_number == int.
:- type depth_number == int.
:- type trace_port_type
--> call
; exit
; redo
; fail
; ite_cond
; ite_then
; ite_else
; neg_enter
; neg_success
; neg_failure
; disj
; switch
; nondet_pragma_first
; nondet_pragma_later
; exception.
:- type pred_or_func
--> predicate
; function.
:- type declarated_module_name == string.
:- type defined_module_name == string.
:- type proc_name == string.
:- type arity == int.
:- type mode_number == int.
:- type determinism == int.
:- type goal_path_string == string.
:- type procedure --> proc(
pred_or_func,
declarated_module_name,
proc_name,
arity,
mode_number).
:- type arguments == list(univ).


Here are functions that eases the access of the event attributes:


:- func chrono(event::in) = (event_number::out) is det.
:- func call(event::in) = (call_number::out) is det.
:- func depth(event::in) = (depth_number::out) is det.
:- func port(event::in) = (trace_port_type::out) is det.
:- func proc_type(event::in) = (pred_or_func::out) is det.
:- func decl_module(event::in) = (declarated_module_name::out) is det.
:- func def_module(event::in) = (defined_module_name::out) is det.
:- func proc_name(event::in) = (proc_name::out) is det.
:- func proc_arity(event::in) = (arity::out) is det.
:- func proc_mode_number(event::in) = (mode_number::out) is det.
:- func proc(event::in) = (procedure::out) is det.
:- func determinism(event::in) = (determinism::out) is det.
:- func goal_path(event::in) = (goal_path_string::out) is det.
:- func arguments(event::in) = (arguments::out) is det. (*)


(*) To be able to retrieve arguments, you to need to have the opium parameter
`collect_arg' set to yes (`man collect_arg.' for more details).

Then, this file is used to generate the Mercury module `collect.m', which is compiled and dynamically linked with the current execution. When a `collect' request is made from the external debugger, a variable of type collected_type is first initialized (with initialize/1) and then updated (with filter/4) for all the events of the remaining execution. When the fourth argument of filter is equal to yes, or when the end of the execution is reached, the last value of the collecting variable is send to Morphine.

collect/2 can be seen as fold/4 meta-predicate except that (1) the initialization and the updating of the accumulator is done via Mercury predicates defined in a separate file (2) it does not take a list as argument but operates on the fly on a list of events (3) we can stop the process at anytime thanks the fourth argument of filter/4.

Commands

collect(File, Result)    
If File contains the implementation of the Mercury predicates initialize/1 and filter/4, collect(File, Result) calls filter/4 with each event of the execution and an accumulator initialized by initialize/1, and returns the final value in Result.The fourth argument of filter is a flag that is set to `continue' or `stop' depending if you want to continue or stop the monitoring process; this useful if one want to be able to stop the monitoring process before the last event is reached.

Here is an example of a simple monitor that counts calls. If a file `count_call' contains the following statements:


:- import_module int.
:- type collected_type == int.


initialize(0).


filter(Event, AccIn, AccOut, continue) :-
( port(Event) = call ->
AccOut = AccIn + 1
;
AccOut = AccIn
).

Then the command `collect(count_call, Result)' will unify Result with the number of calls that occur during the program execution.
File : is_atom_or_string
Result : is_atom_or_var
type of command : opium

Primitives

compile_collect    
Compile the module `collect.m'.

current_grade(Grade)    
Retrieves the grade the current program execution has been compiled with.
Grade : var

generate_collect(File)    
Generates a Mercury module named `collect.m' from file File; File should contain the definition of the accumulator type (collected_type), initialize/1 and filter/4 predicates.
File : is_atom_or_var

dyn_link_collect    
Dynamically links the collect module with the currently run program.

run_collect(Result)    
Executes the collect command provided that collect.m has been correctly, generated, compiled and dynamically linked with the current program execution.
Result : var

Parameters

collect_arg(YesOrNo)    
Parameter which tells whether it is possible to use arguments/1 within collect:filter/4. If you do not use arguments, it is better to set this parameter to `no' since when arguments are very big, it might slow down the execution of collect a lot.
YesOrNo : member([yes, no])
default value : collect_arg(no)
type of parameter : single


next up previous contents index
Next: Scenario ``control_flow'' Up: Morphine - Reference Manual Previous: Scenario ``step_by_step''
jahier@irisa.fr