A flavour of programming in Opium

Erwan Jahier Erwan.Jahier at irisa.fr
Sat Jun 6 01:57:46 AEST 1998


I think most of you aren't aware of what can be easily done within
Opium. 
The reason is certainly that we haven't show you; so please let give me
a quick try.

I randomly quoted part of the discussion about the command set for the
internal trace based debugger and I show how it can be done within Opium
(I didn't try to implement it in the optimal way, it is just to show you
how easy it can be).


Before doing that, just a quick presentation of Opium:
Opium = a Prolog top-level interpreter 
	+ f_get/11 (forward move in the trace history) 
	+ current_line/11 (retrieving informations about the current event).


Each slot of f_get/11 and current_line/11 corresponds to a particular
type of information attached to the current event (Chrono, CallNumber,
Depth, Port, ModuleName, PredName, Arity, ModeNumber, Determinism,
ArgumentList, GoalPath).

The *print_line* predicate retrieve the different information related to
the current event (thanks to current_line/11) and print it. For example:

[opium]: print_line.
11:   4  [ 4]    switch  foo/2 (3, 8) d2; 

Of course, you print only the slots you want. For example, the module
name and the determinism are boring most of the time and you don't want
to always see them; you can set on and off the printing of a particular
slot very easily (something like display_off(module) /
display_on(module)).
 
Now let's go !
-------------------------------------------------------------
Zoltan Somogyi wrote:
> FORWARD MOVEMENT COMMANDS
> 
> skip [<num>]
>         If this command is given at event <cur>, continues execution until
>         event <cur> + <num>. The default value of <num> is 1.

jump_np(Num) :-		% _np stands for "no print"
	current_chrono(C),
	NewC is C + Num,
	f_get(NewC, -,-,-,-,-,-,-,-,-,-).	

jump(Num) :-	
	jump_np(Num),
	print_line.

% Note: current_chrono(C) :- 
%		current_line(C,-,-,-,-,-,-,-,-,-,-).

> goto <num>
>         Continues execution until event <num> provided that the number
>         of the current event is smaller than <num>. Otherwise it reports
>         an error.

goto(Num) :-
	f_get(Num, -,-,-,-,-,-,-,-,-,-).


> finish
>         Continues execution until it reaches a final (EXIT or FAIL) port
>         of the call to which the current event refers. Reports an error
>         if the current event refers to a final port.
% This is rather called skip in most of the Prolog tracer
skip_np :-
	current_pred(PredName),
	f_get(-,-,-,[exit, port],-, PredName,-,-,-,-).

skip :-
	finish_np,
	print_line.
% if you, user, don't like that name, you can define your own predicate:
finish :- 
	skip.

> forward
>         Continues the program until the program resumes forward execution,
>         i.e. until it reaches a non-final port inside any predicate. Reports
>         an error if the current event refers to a non-final port.

forward :-
	f_get(-,-,-,[disj, swtc, then, else],-,-,-,-,-,-).

Oww! Zoltan just adds 2 new internal ports, I need to reimplement that
feature )-;
Hopefuly, as programming in opium is simple, it is not a very hard job
:-)

forward :-
	f_get(-,-,-,[disj, swtc, then, else, frst, latr],-,-,-,-,-,-).


> continue
>         Continues execution until it reaches the end of the program.

continue :-
	f_get(1,1,1,exit,-,main,-,-,-,-,-,-).

> 
> DEBUGGER STATE MANIPULATION COMMANDS
> 
> spy <module name> <predicate name>
>         Puts a spy point on the named predicate in the named module.

spy(ListPred) :-
	getval(list_of_spy_points, ListSP),
	union(ListPred, ListSP, NewList),
	setval(list_of_spy_points, NewListSP).

unspy(ListPred) :-
	getval(list_of_spy_points, ListSP),
	subtract(ListSP, ListPred, NewListSP),
	setval(list_of_spy_points, NewListSP).	

leap_np :-
	getval(list_of_spy_points, List),
	f_get(-,-,-,-,-,List,-,-,-,-,-,-).

leap :-
	leap_np,
	print_line.

> list
>         Lists all current spy and break points, their numbers and their states.

list_spy_points(List) :-
	opium_getval(list_of_spy_points, List).

---------------------------------------------------------
Peter Schachte wrote:
> It would be very useful to be able to (separately) turn on and off stopping
> and printing based on port. 

Well, it's quite easy in Opium,
You can use the following predicate to print your trace line:

print_at_port(Port) :-
	(current_port(Port) -> 
		print_line 
	; 
		true
	).

Or if you want to print at more than one port:

print_at_ports(ListPort) :-
	current_port(Port),
	( is_element_of_the_list(Port, ListPort) ->
		print_line 
	; 
		true
	).
	
---------------------------------------------------------



-- 
R1.



More information about the developers mailing list