[m-dev.] add goal path at external ports
Erwan.Jahier at irisa.fr
Wed Jan 27 22:14:52 AEDT 1999
| > Sure. But if I want to work out the coverage ratio of a several millions events
| > execution, it would be far more too inneffective (see after).
| I don't understand.
Because you need to stop at each internal event, push the path, the call number
and the name of the procedure to the stack. Then you also need to stop at each
external event, you need to look up in the stack, ...
With what I propose, you only stop at external events, and not all of them;
only the one not covered yet (this makes a big difference in you have a
strongly recursive procedures for example, where you always have the path
Here is the pseudo-Opium code that do that:
% type paths ---> paths(
% list(predicate_name)), % predicate call to be covered
% list(predicate_name), % predicate where that event occur (ancestor))
% list(goalpath), % goal path where the the call is made
% list(list(port)) % list of ports to be covered
% For example, if the paths to be covevered are :
% ([foo1, foo2], [bar, bar], ['e', 'd1;t'], [[exit], [exit, fail]]),
% it means that for the occurence of foo1 in the else branch of bar,
% we want to see 1 exit (because it is det) and for the occurence of
% foo2 in the 'then' branch of the '1st disjunction' of bar, we want
% to see 1 exit and 1 fail (because it is semidet).
% Those paths can be generated automaticly from the HLDS.
%:- pred coverage(paths, paths).
%:- mode coverage(in, out) is semidet.
coverage(ToBeCoveredIn, ToBeCoveredOut) :-
ToBeCoveredIn = paths(ListPred, _, _, _),
f_get([pred = ListPred, port = [exit, fail]])
update_paths(Pred, Ancestor, Path, Port,
% End of the execution is reached
ToBeCoveredOut = ToBeCoveredIn
| > Well, is there any reason why this can't be done at compile time (i.e. when
| > generating the code and the MR_trace statements ?)
| No, this could be done. But I forgot to mention my main point: I
| think this could be done more easily in Opium.
I know that.
Could it be done at compile time ?
(which is my original question)
| I disagree. If you record the most recent internal event at each depth,
| then when you get an external event at depth N you have:
I don't want to stop the execution at each internal events because it is far
too slow. I've tried once to stop at every event of a 3 millions events
execution ; it processes for more than one day !
| i) the immediate ancestor (ie the procedure of the most
| recent internal event at depth N - 1),
| ii) the path to the called atom within the body of the
| ancestor (ie the goal path of the most recent
| internal event at depth N - 1), and
| iii) the procedure being called (ie the procedure of the current
| The atom b, above, is executed if and only if a 'CALL b' event is reached
| at depth N (for some N) when the most recent event at depth N - 1 has
| procedure p and goal path "?;d1".
| However, as I mentioned previously, there is no way to distinguish
| between two calls to the same procedure in the same conjunction.
More information about the developers