1\documentclass{article}
2
3\usepackage[latin1]{inputenc}
4
5\begin{document}
6
7\title{ASSERT: Dynamic Verification of Assertions on Function Types}
8\author{Thomas Sturm\\
9Dpto.~de Matem�ticas Estad�stica y Computaci�n\\
10Universidad de Cantabria\\
1139071 Santander, Spain\\
12Email: \texttt{sturm@redlog.eu}}
13\date{July 18, 2010}
14\maketitle
15
16\begin{abstract}
17  ASSERT admits to add to symbolic mode RLISP code assertions (partly)
18  specifying \emph{types} of the arguments and results of RLISP expr
19  procedures. These types can be associated with functions testing the
20  validity of the respective arguments during runtime.
21\end{abstract}
22
23\section{Loading and Using}
24The package is loaded using \texttt{load\_package} or
25\texttt{load!-package} in algebraic or symbolic mode, resp. There is a
26central switch \texttt{assertcheck}, which is off by default. With
27\texttt{assertcheck} off, all type definitions and assertions described
28in the sequel are ignored and have the status of comments. For
29verification of the assertions it most be turned on (dynamically) before
30the first relevant type definition or assertion.
31
32ASSERT aims at the dynamic analysis of RLISP expr procedure in symbolic
33mode. All uses of \texttt{typedef} and \texttt{assert} discussed in the
34following have to take place in symbolic mode. There is, in contrast, a
35final print routine \texttt{assert\_analyze} that is available in both
36symbolic and algebraic mode.
37
38\section{Type Definitions}
39Here are some examples for definitions of types:
40\begin{verbatim}
41typedef any;
42typedef number checked by numberp;
43typedef sf checked by sfpx;
44typedef sq checked by sqp;
45\end{verbatim}
46The first one defines a type \texttt{any}, which is not possibly checked
47by any function. This is useful, e.g., for functions which admit any
48argument at one position but at others rely on certain types or
49guarantee certain result types, e.g.,
50\begin{verbatim}
51procedure cellcnt(a);
52   % a is any, returns a number.
53   if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
54\end{verbatim}
55
56The other ones define a type \texttt{number}, which can be checked by
57the RLISP function \texttt{numberp}, a type \texttt{sf} for standard
58forms, which can be checked by the function \texttt{sfpx} provided by
59ASSERT, and similarly a type for standard quotients.
60
61All type checking functions take one argument and return extended
62Boolean, i.e., non-nil iff their argument is of the corresponding type.
63
64\section{Assertions}
65Having defined types, we can formulate assertions on expr procedures in
66terms of these types:
67\begin{verbatim}
68assert cellcnt: (any) -> number;
69assert addsq: (sq,sq) -> sq;
70\end{verbatim}
71Note that on the argument side parenthesis are mandatory also with only
72one argument. This notation is inspired by Haskell but avoids the
73intuition of currying.\footnote{This notation has benn suggested by C. Zengler}
74
75Assertions can be dynamically checked only for expr procedures. When
76making assertions for other types of procedures, a warning is issued and
77the assertion has the status of a comment.
78
79It is important that assertions via assert come after the definitions of
80the used types via \texttt{typedef} and also after the definition of the
81procedures they make assertions on.
82
83A natural order for adding type definitions and assertions to the source
84code files would be to have all typedefs at the beginning of a module
85and assertions immediately after the respective functions.
86Fig.~\ref{FIG:assMod} illustrates this. Note that for dynamic checking
87of the assertions the switch \texttt{assertcheck} has to be on during
88the translation of the module; i.e., either when reading it with
89\texttt{in} or during compilation. For compilation this can be achieved
90by commenting in the \texttt{on assertcheck} at the beginning or by
91parameterizing the Lisp-specific compilation scripts in a suitable way.
92
93An alternative option is to have type definitions and assertions for
94specific packages right after \texttt{load\_package} in batch files as
95illustrated in Fig.~\ref{FIG:assBat}.
96\begin{figure}
97  \begin{small}
98\begin{verbatim}
99module sizetools;
100
101load!-package 'assert;
102
103% on assertcheck;
104
105typedef any;
106typedef number checked by number;
107
108procedure cellcnt(a);
109   % a is any, returns a number.
110   if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
111
112assert cellcnt: (any) -> number;
113
114% ...
115
116endmodule;
117
118end;  % of file
119\end{verbatim}
120  \end{small}
121  \caption{Assertions in the source code.\label{FIG:assMod}}
122\end{figure}
123
124\begin{figure}
125  \begin{small}
126\begin{verbatim}
127load_package sizetools;
128load_package assert;
129
130on assertcheck;
131
132lisp <<
133   typedef any;
134   typedef number checked by numberp;
135
136   assert cellcnt: (any) -> number
137>>;
138
139% ... computations ...
140
141assert_analyze();
142
143end;  % of file
144\end{verbatim}
145  \end{small}
146  \caption{Assertions in a batch file.\label{FIG:assBat}}
147\end{figure}
148
149\section{Dynamic Checking of Assertions}
150Recall that with the switch \texttt{assertcheck} off at translation
151time, all type definitions and assertions have the status of comments.
152We are now going to discuss how these statements are processed with
153\texttt{assertcheck} on.
154
155\texttt{typedef} marks the type identifier as a valid type and possibly
156associates the given typechecking function with it. Technically, the
157property list of the type identifier is used for both purposes.
158
159\texttt{assert} encapsulates the procedure that it asserts on into
160another one, which checks the types of the arguments and of the result
161to the extent that there are typechecking functions given. Whenever some
162argument does not pass the test by the typechecking function, there is a
163warning message issued. Furthermore, the following numbers are counted
164for each asserted function:
165\begin{enumerate}
166\item The number of overall calls,
167\item the number of calls with at least one assertion violation,
168\item the number of assertion violations.
169\end{enumerate}
170These numbers can be printed anytime in either symbolic or algebraic
171mode using the command \texttt{assert\_analyze()}. This command at the
172same time resets all the counters.
173
174Fig.~\ref{FIG:sample} shows an interactive sample session.
175%
176\begin{figure}
177  \begin{small}
178\begin{verbatim}
1791: symbolic$
180
1812* load_package assert$
182
1833* on assertcheck$
184
1854* typedef sq checked by sqp;
186sqp
187
1885* assert negsq: (sq) -> sq;
189+++ negsq compiled, 13 + 20 bytes
190
191(negsq)
192
1936* assert addsq: (sq,sq) -> sq;
194+++ addsq compiled, 14 + 20 bytes
195
196(addsq)
197
1987* addsq(simp 'x,negsq simp 'y);
199
200((((x . 1) . 1) ((y . 1) . -1)) . 1)
201
2028* addsq(simp 'x,negsq numr simp 'y);
203
204*** assertion negsq: (sq) -> sq violated by arg1 (((y . 1) . 1))
205
206*** assertion negsq: (sq) -> sq violated by result (((y . -1) . -1))
207
208*** assertion addsq: (sq,sq) -> sq violated by arg2 (((y . -1) . -1))
209
210*** assertion addsq: (sq,sq) -> sq violated by result (((y . -1) . -1))
211
212(((y . -1) . -1))
213
2149* assert_analyze()$
215------------------------------------------------------------------------
216function          #calls              #bad calls   #assertion violations
217------------------------------------------------------------------------
218addsq                  2                       1                       2
219negsq                  2                       1                       2
220------------------------------------------------------------------------
221sum                    4                       2                       4
222------------------------------------------------------------------------
223\end{verbatim}
224  \end{small}
225  \caption{An interactive sample session.\label{FIG:sample}}
226\end{figure}
227
228\section{Switches}
229As discussed above, the switch \texttt{assertcheck} controls at
230translation time whether or not assertions are dynamically checked.
231
232There is a switch \texttt{assertbreak}, which is off by default. When
233on, there are not only warnings issued for assertion violations but the
234computations is interrupted with a corresponding error.
235
236The statistical counting of procedure calls and assertion violations is
237toggled by the switch \texttt{assertstatistics}, which is on by default.
238
239\section{Efficiency}
240The encapsulating functions introduced with assertions are automatically
241compiled.
242
243% sturm@lennier[~/Desktop] time redpsl < taylor.tst > /dev/null
244
245% real	0m0.798s
246% user	0m0.584s
247% sys	0m0.166s
248% sturm@lennier[~/Desktop] time redcsl < taylor.tst > /dev/null
249
250% real	0m1.975s
251% user	0m1.808s
252% sys	0m0.143s
253% sturm@lennier[~/Desktop] time redpsl < taylor.tst > /dev/null
254
255% real	0m0.442s
256% user	0m0.316s
257% sys	0m0.122s
258% sturm@lennier[~/Desktop] time redcsl < taylor.tst > /dev/null
259
260% real	0m0.610s
261% user	0m0.491s
262% sys	0m0.115s
263
264We have experimentally checked assertions on the standard quotient
265arithmetic \texttt{addsq}, \texttt{multsq}, \texttt{quotsq},
266\texttt{invsq}, \texttt{negsq} for the test file \texttt{taylor.tst} of
267the TAYLOR package. For CSL we observe a slowdown of factor 3.2, and for
268PSL we observe a slowdown of factor 1.8 in this particular example,
269where there are 323\,750 function calls checked altogether.
270
271The ASSERT package is considered an analysis and debugging tool.
272Production system should as a rule not run with dynamic assertion
273checking. For critical applications, however, the slowdown might be
274even acceptable.
275
276\section{Possible Extensions}
277Our assertions could be used also for a static type analysis of source
278code. In that case, the type checking functions become irrelevant. On
279the other hand, the introduction of variouse unchecked types becomes
280meaningful.
281
282In a model, where the source code is systematically annotated with
283assertions, it is technically no problem to generalize the specification
284of procedure definitions such that assertions become implicit. For
285instance, one could \emph{optionally} admit procedure definitions like
286the following:
287\begin{verbatim}
288procedure cellcnt(a:any):number;
289   if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
290\end{verbatim}
291\end{document}
292