This part describes advanced uses of LPdoc and the Ciao Playground to create and maintain interactive tutorials for analysis and verification using CiaoPP.
These documents require the features provided in the exfilter bundle, which extends LPdoc and the playground with functionality to extract, filter, and compare the output of program analyses, both statically and dynamically.
Messages and output generated during Ciao compilation or CiaoPP analysis, for a particular code snippet, can be filtered and included in manuals with the following LPdoc command:
@exfilter{Code}{Action, FlagsValues, Filters}.
In order to enable this functionality it is necessary to include this line in the LPdoc document configuration files (e.g., SETTINGS.pl):
load_doc_module := exfilter(exfilter_lpdoc).This process happens in two phases: first the document is processed to identify the different (compilation, analysis, verification, etc.) tasks, then the ciao-exfilter command needs to be executed to process the tasks and filter the results necessary for the manual. Typically the results are statically committed in the respository, which enables easy detection of regressions.
For instance, consider the app/3 program:
:- module(_,app/3,[assertions]). :- pred app(Xs, Ys, Zs) : ( list(Xs), list(Ys) ) => list(Zs) . app([], Ys, Ys). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs).where the pred assertion indicates how app/3 should be called in this program. We would like to display the part of the analysis output that shows if the assertion has been checked. This fragment can be generated by including in the source file the following code:
@exfilter{app.pl}{V,output=on,filter=check_pred}
This command is composed of the file that we are looking to filter (app.pl), the analysis and the filter options that we want applied (V,output=on,filter=check_pred). The result is:
:- checked calls app(Xs,Ys,Zs) : ( list(Xs), list(Ys) ). :- checked success app(Xs,Ys,Zs) : ( list(Xs), list(Ys) ) => list(Zs).
FlagsValues is a list of options FlagName=FlagValue where FlagName is a valid CiaoPP flag name. This list is optional and the flags not included in this list will be assumed to take their default value. Check CiaoPP Reference Manual for the different available flags.
The following are very simple examples of use:
@exfilter{app.pl}{A,filter=tpred,absdomain=types}
Output result:
:- true pred app(Xs,Ys,Zs) : ( list(Xs), list(Ys), term(Zs) ) => ( list(Xs), list(Ys), list(Zs) ).
@exfilter{app.pl}{A,ana_cost=resources,filter=tpred_plus}
Output result:
:- true pred app(Xs,Ys,Zs) : ( list(Xs), list(Ys), term(Zs) ) => ( list(Xs), list(Ys), list(Zs) ) + cost(lb,steps,0). :- true pred app(Xs,Ys,Zs) : ( list(Xs), list(Ys), term(Zs) ) => ( list(Xs), list(Ys), list(Zs) ) + cost(ub,steps,inf).
@exfilter{app.pl}{A,ana_cost=resources,assertion=[ub],filter=tpred_plus}
Output result:
:- true pred app(Xs,Ys,Zs) : ( list(Xs), list(Ys), term(Zs) ) => ( list(Xs), list(Ys), list(Zs) ) + cost(ub,steps,inf).
The playground already included specific commands for embedding editable and runnable code in place. The exfilter bundle extends this functionality with additional steps that turn code snippets into exercises. In particular, the analysis and the filtering method are executed directly in the browser.
For example, in this exercise we want the user to correct the singleton variable written in the base case of predicate app/3:
:- module(_,app/3,[assertions]). %! \begin{code} app([], Ys, Yss). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs). %! \end{code} %! \begin{opts} solution=errors,message=singleton %! \end{opts} %! \begin{solution} app([], Ys, Ys). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs). % In our case, we type Yss instead of Ys. %! \end{solution}When users submit their answers, the playground will return appropriate feedback showing the error messages related to the singleton variables. We have defined lpdoc-style commands which mark different parts of the program. The playground identifies the different parts and classifies them. For example, the playground will recognize a solution, a set of filters that we want to apply, and the part of the interactive code that will be shown in the documentation. In this case, the solution will be shown only when the Show solution button is clicked. The code part is always visible. Hence, the previous exercise can be generated by including in the source file the following code:
```ciao_runnable :- module(_,app/3,[assertions]). %! \begin{code} app([], Ys, Yss). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs). %! \end{code} %! \begin{opts} solution=errors,message=singleton %! \end{opts} %! \begin{solution} app([], Ys, Ys). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs). % In our case, we type Yss instead of Ys. %! \end{solution} ```
For the inclusion of exercises in the documentation three distinct modes of exercises have been developed:
%! \begin{code} :- module(_, [app/3], [assertions]). :- pred app(A,B,C) : (list(A), list(B)) => var(C). app([],Y,Y). app([X|Xs], Ys, [X|Zs]) :- app(Xs,Ys,Zs). %! \end{code} %! \begin{opts} solution=verify_assert %! \end{opts} %! \begin{solution} :- module(_, [app/3], [assertions]). :- pred app(A,B,C) : (list(A), list(B)) => list(C). app([],Y,Y). app([X|Xs], Ys, [X|Zs]) :- app(Xs,Ys,Zs). %! \end{solution}
It can be generated by including in the source file the following code:
```ciao_runnable :- module(_, [app/3], [assertions]). :- pred app(A,B,C) : (list(A), list(B)) => var(C). app([],Y,Y). app([X|Xs], Ys, [X|Zs]) :- app(Xs,Ys,Zs). %! \end{code} %! \begin{opts} solution=verify_assert %! \end{opts} %! \begin{solution} :- module(_, [app/3], [assertions]). :- pred app(A,B,C) : (list(A), list(B)) => list(C). app([],Y,Y). app([X|Xs], Ys, [X|Zs]) :- app(Xs,Ys,Zs). %! \end{solution} ```Note that you can also generate interactive examples, for example:
%! \begin{code} :- module(_,app/3,[assertions]). :- pred app(Xs, Ys, Zs) : ( list(Xs), list(Ys) ) => list(Zs) . app([], Ys, Ys). app([X|Xs], Ys, [X|Zs]) :- app(Xs, Ys, Zs). %! \end{code} %! \begin{opts} A,ana_det=nfdet,filter=tpred_plus %! \end{opts}This block runs analysis on the program with a determinism domain and displays the true assertions including comp properties.