Library(prolog_coverage) - working with predicates generated via persistent/1

$ swipl --version
SWI-Prolog version 10.0.0 for x64-win64

Using library(prolog_coverage) on a module that uses library(persistency).

For code coverage for persistent/1 was able to increase the code coverage by adding tests for the dynamicly created four predicates resulting in this

   90 ### ⮰
      ++20 ⮰
      ++4,727 ⮰
      ++21,486 ⮰
      +55,950-20             :- persistent(pred_def(name:atom, arity:integer, module:atom, file:atom, line:integer)).

There is now just the one remaining ### that I have no idea of what it could be.

Any ideas? Is it a predicate, an artifact of code coverage that can be removed, other?

Any ideas on how to get a line in the cov report to show what it could be?


Gave Claude the links to the SWI-Prolog library code on GitHub and noted the relevant files in the project and Claude thinks

   90 ### ⮰                          ← The directive itself: never "executed"
      ++20 ⮰                          ← Generated predicate variant 1
      ++4,727 ⮰                       ← Generated predicate variant 2
      ++21,486 ⮰                      ← Generated predicate variant 3
      +55,950-20                      ← Generated predicate variant 4
             :- persistent(pred_def(name:atom, arity:integer, module:atom, file:atom, line:i

If that is true would like to find a way to remove such lines from the cov report so that the report shows 100% coverage for the module. Currently Claude will search for ### lines and thus it is like having a wrench thrown into the clock works.

I don’t think that is true. The directive is term-expanded to a set of predicates. I suspect one of them is not used by your tests. Which one is a bit hard to tell. Ideally the system should provide better feedback for this, but I’m not sure how.

I’d create a module with only this declaration and list the content so you can understand what is going on.

1 Like

Result confirms that is true.



There are five, not four generated predicates from persistent/1.

From documentation

The persistent/1 expands each declaration into four predicates:

  • name(Arg, ...)
  • assert_name(Arg, ...)
  • retract_name(Arg, ...)
  • retractall_name(Arg, ...)

using

:- persistent(pred_def(name:atom, arity:integer, module:atom, file:atom, line:integer)).

the following are generated

Generated predicate type
pred_def/5 base
assert_pred_def/5 assert_
asserta_pred_def/5 asserta_
retract_pred_def/5 retract_
retractall_pred_def/5 retractall_

   90 ++21,486 ⮰
      ++20 ⮰
      ++4,987 ⮰
      +55,950-20 ⮰
      ++20                   :- persistent(pred_def(name:atom, arity:integer, module:atom, file:atom, line:integer)).

Jan updated the SWI-Prolog documentation for library(persistency)

Filename: test_persistency.pl

% Minimal Fixture: Single persistent/1 directive with arity 1
% Purpose: Isolate coverage behavior for one persistent declaration
%
% This module tests the simplest case:
% - One persistent/1 directive
% - Arity 1 (single argument)
% - Generates 5 predicates: foo/1, assert_foo/1, asserta_foo/1, retract_foo/1, retractall_foo/1

:- module(test_persistency, []).

:- use_module(library(persistency)).

% Single persistent declaration - should generate exactly 5 predicates
:- persistent(foo(value:any)).
$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 10.0.0)

4 ?- [test_persitency].
true.

5 ?- findall(Name/Arity,         (current_predicate(test_persistency:Name/Arity),         sub_atom(Name, _, _, _, foo)),         Preds),sort(Preds, 
SortedPreds),forall(member(Name/Arity, SortedPreds), format('~w/~w~n', [Name, Arity])).
assert_foo/1
asserta_foo/1
foo/1
retract_foo/1
retractall_foo/1
Preds = [retract_foo/1, retractall_foo/1, foo/1, asserta_foo/1, assert_foo/1],
SortedPreds = [assert_foo/1, asserta_foo/1, foo/1, retract_foo/1, retractall_foo/1].

Added to the docs.

1 Like