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