1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
|
<html>
<head><title>GUARDS-AND-EVALUATION.html -- ACL2 Version 3.1</title></head>
<body text=#000000 bgcolor="#FFFFFF">
<h3>GUARDS-AND-EVALUATION</h3>the relationship between guards and evaluation
<pre>Major Section: <a href="GUARD.html">GUARD</a>
</pre><p>
The guard has no effect on the logical axiom added by the definition
of a function. It does, however, have consequences for how calls of
that function are evaluated in ACL2. We begin by explaining those
consequences, when ACL2 is in its default ``mode,'' i.e., as
originally brought up. In subsequent discussion we'll consider
other ways that guards can interact with evaluation.<p>
For more about guards in general, see <a href="GUARD.html">guard</a>. For in-depth discussion of the
interaction between the <a href="DEFUN-MODE.html">defun-mode</a> and guard checking,
see <a href="SET-GUARD-CHECKING.html">set-guard-checking</a>, see <a href="GUARD-EVALUATION-TABLE.html">guard-evaluation-table</a>,
see <a href="GUARD-EVALUATION-EXAMPLES-SCRIPT.html">guard-evaluation-examples-script</a>, and
see <a href="GUARD-EVALUATION-EXAMPLES-LOG.html">guard-evaluation-examples-log</a>. Also see <a href="GENERALIZED-BOOLEANS.html">generalized-booleans</a> for
discussion about a subtle issue in the evaluation of certain Common Lisp
functions.
<p>
<em>Guards and evaluation I: the default</em><p>
Consider the following very simple definition.
<pre>
(defun foo (x) (cons 1 (cdr x)))
</pre>
First consider how raw Common Lisp behaves when evaluating calls of
this function. To evaluate <code>(foo x)</code> for some expression <code>x</code>, first
<code>x</code> is evaluated to some value <code>v</code>, and then <code>(cons 1 (cdr x))</code> is
evaluated with <code>x</code> bound to <code>v</code>. For example, if <code>v</code> is <code>(cons 'a 3)</code>, then
Common Lisp computes <code>(cons 1 3)</code>. But if (for example) <code>v</code> is a
number, e.g., <code>7</code>, then there is no way to predict what Common
Lisp might do. Some implementations would cause ``sensible''
errors, others might return nonsense, still others might crash the
host machine. The results tend toward the catastrophic if the call
of <code>foo</code> in question is in compiled code.<p>
Now by default, ACL2 evaluates calls of <code>foo</code> exactly as Common
Lisp does, except that it uses guards to check the ``legality'' of
each function call. So for example, since <code>(cdr x)</code> has a guard
of <code>(or (consp x) (equal x nil))</code>, the call <code>(foo 7)</code> would cause a
``guard violation,'' as illustrated below.
<pre>
ACL2 !>(foo 7)<p>
ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CDR 7).<p>
ACL2 !>
</pre>
Thus, the relation between evaluation in ACL2 and evaluation in
Common Lisp is that the two produce the very same results, provided
there is no guard violation.<p>
<em>Guards and evaluation II:</em> <code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code>.<p>
The ACL2 logic is a logic of total functions. That is, every
application of a function defined has a completely specified result.
See the <a href="DOCUMENTATION.html">documentation</a> for each individual primitive for the
specification of what it returns when its guard is violated; for
example, see <a href="CDR.html">cdr</a>.<p>
The presence of guards thus introduces a choice in the sense of
evaluation. When you type a form for evaluation do you mean for
guards to be checked or not? Put another way, do you mean for the
form to be evaluated in Common Lisp (if possible) or in the ACL2
logic? Note: If Common Lisp delivers an answer, it will be the
same as in the logic, but it might be erroneous to execute the form
in Common Lisp. For example, the ACL2 logic definition of <code><a href="CDR.html">cdr</a></code>
implies that the <code><a href="CDR.html">cdr</a></code> of an <a href="ATOM.html">atom</a> is <code>nil</code>; see <a href="CDR.html">cdr</a>. So:
should <code>(cdr 7)</code> cause a guard violation error or return <code>nil</code>?<p>
The top-level ACL2 loop has a variable which controls which sense of
execution is provided. By default, ``guard checking'' is on, by which we
mean that guards are checked at runtime, in the sense already described. To
allow execution to proceed in the logic when there is a guard violation, do
<code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code><code> nil</code>; or evaluate
<code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code><code> :none</code> to skip guard checking entirely. To
turn ``guard checking'' back on, execute the top-level form
<code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code><code> t</code>. The status of guard checking
reflected in the <a href="PROMPT.html">prompt</a>; guard-checking is ``on'' when the <a href="PROMPT.html">prompt</a>
contains an exclamation mark (also see <a href="DEFAULT-PRINT-PROMPT.html">default-print-prompt</a>). For example,
<pre>
ACL2 !>
</pre>
means guard checking is on and
<pre>
ACL2 >
</pre>
means guard checking is off. The exclamation mark can be thought of
as ``barring'' certain computations. The absence of the mark
suggests the absence of error messages or unbarred access to the
logical axioms. Thus, for example
<pre>
ACL2 !>(car 'abc)
</pre>
will signal an error, while
<pre>
ACL2 >(car 'abc)
</pre>
will return <code>nil</code>. To return to our previous example: with guard
checking off, <code>(foo 7)</code> evaluates to <code>(cons 1 nil)</code>. Also
see <a href="SET-GUARD-CHECKING.html">set-guard-checking</a>.<p>
<em>Guards and evaluation III: guard verification</em><p>
Consider the defininition of <code>foo</code> given above, but modified so
that a reasonable guard of <code>(consp x)</code> is specified, as shown below.
<pre>
(defun foo (x)
(declare (xargs :guard (consp x)))
(cons 1 (cdr x)))
</pre>
We say ``reasonable guard'' above because if <code>x</code> is such that
<code>(consp x)</code> holds, then the call of <code><a href="CDR.html">cdr</a></code> in the evaluation of
<code>(foo x)</code> will not cause a guard violation. Thus, it ``should'' be
legal to evaluate <code>(foo x)</code>, for any such <code>x</code>, simply by
evaluating this form in raw Common Lisp.<p>
The <code><a href="VERIFY-GUARDS.html">verify-guards</a></code> event has been provided for this purpose.
Details may be found elsewhere; see <a href="VERIFY-GUARDS.html">verify-guards</a>. Briefly,
for any defined function <code>fn</code>, the event <code>(verify-guards fn)</code>
attempts to check the condition discussed above, that whenever <code>fn</code>
is called on arguments that satisfy its guard, the evaluation of
this call will proceed without any guard violation. (Moreover, the
guard itself should be evaluable without any guard violation.) If
this check is successful, then future calls of this sort will be
evaluated in raw Common Lisp.<p>
Returning to our example above, the <code>(verify-guards foo)</code> will
succeed because the guard <code>(consp x)</code> of <code>foo</code> implies the guard
generated from the call <code>(cdr x)</code> in the body of the definition,
namely, <code>(or (consp x) (equal x nil))</code> (see <a href="CDR.html">cdr</a>). Then the
evaluation of <code>(foo (cons 'a 3))</code> will take place in raw Common
Lisp, because <code>(cons 'a 3)</code> satisfies the guard of <code>foo</code>.<p>
This ability to dive into raw Common Lisp hinges on the proof that
the guards you attach to your own functions are sufficient to ensure
that the guards encountered in the body are satisfied. This is
called ``guard verification.'' Once a function has had its guards
verified, then ACL2 can evaluate the function somewhat faster (but
see ``Guards and evaluation V: efficiency issues'' below). Perhaps
more importantly, ACL2 can also guarantee that the function will be
evaluated correctly by any implementation of Common Lisp (provided
the guard of the function is satisfied on the input). That is, if
you have verified the guards of a system of functions and you have
determined that they work as you wish in your host ACL2 (perhaps by
proving it, perhaps by testing), then they will work identically in
any Common Lisp.<p>
There is a subtlety to our treatment of evaluation of calls of
functions whose guards have been verified. If the function's guard
is not satisfied by such a call, then no further attempt is made to
evaluate any call of that function in raw lisp during the course of
evaluation of that call. This is obvious if guard checking is on,
because an error is signalled the first time its guard is violated;
but in fact it is also true when guard checking is off.
See <a href="GUARD-EXAMPLE.html">guard-example</a> for an example.<p>
<em>Guards and evaluation IV: functions having :program mode</em><p>
Strictly speaking, functions in <code>:</code><code><a href="PROGRAM.html">program</a></code> mode (see <a href="DEFUN-MODE.html">defun-mode</a>) do
not have definitions in the ACL2 logic. So what does it mean to evaluate
calls of such functions in ACL2? In general we treat <code>:</code><code><a href="PROGRAM.html">program</a></code>
functions much as we treat <code>:</code><code><a href="LOGIC.html">logic</a></code> functions whose guards have been
verified, except that when no error occurs then the corresponding raw Lisp
function is always called. (We say ``in general'' because there are
exceptions, discussed in the ``Aside'' just below.) Note that when the guard
of a function in <code>:</code><code><a href="LOGIC.html">logic</a></code> mode is violated, there is still a value
that the ACL2 logic proves is equal to the given call. But the same cannot
be said for a function in <code>:</code><code><a href="PROGRAM.html">program</a></code> mode. Nevertheless, for the
sake of convenience we go ahead and evaluate the corresponding raw Lisp
function except in the situation where the guard is violated and
guard-checking is on, aside from the following:<p>
<strong>Aside</strong>. There are exceptions to the use of raw Lisp, discussed just
above, to evaluate calls of <code>:</code><code><a href="PROGRAM.html">program</a></code> mode functions. The primary
one is that after <code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code><code> :none</code>, evaluation of
user-defined <code>:</code><code><a href="PROGRAM.html">program</a></code> mode function calls is done in the ACL2
logic, not in raw Lisp. The more obscure exception is that during expansion
of macros and <code><a href="MAKE-EVENT.html">make-event</a></code> forms, and during evaluation of <code><a href="DEFCONST.html">defconst</a></code>
forms, ACL2 enters a ``safe mode'' in which this escape to raw Lisp is
prevented. The following example illustrates how the user can experiment
directly with safe mode, though it is preferred to use
<code>:</code><code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code><code> :none</code> if you are happy to skip all guard
checking and evaluate forms in the logic.
<pre>
ACL2 !>(defun foo (x)
(declare (xargs :mode :program :guard t))
(car x))<p>
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: SIMPLE-ERROR]<p>
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this process.
[1] ACL2(2): :pop
ACL2 !>(assign safe-mode t)
T
ACL2 !>(foo 3)<p>
ACL2 Error in TOP-LEVEL: The guard for the function symbol CAR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CAR 3). See :DOC wet for how you might be able to get an error
backtrace.<p>
ACL2 !>(assign safe-mode nil)
NIL
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: SIMPLE-ERROR]<p>
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this process.
[1] ACL2(2):
</pre>
The other exception occurs after <code><a href="SET-GUARD-CHECKING.html">set-guard-checking</a></code> can be called with
a value of <code>:all</code>; see <a href="SET-GUARD-CHECKING.html">set-guard-checking</a>.
<strong>End of aside.</strong><p>
Thus, as with <code>:</code><code><a href="LOGIC.html">logic</a></code> functions: when a guard has been
satisfied on a call of a function with <code>:</code><code><a href="PROGRAM.html">program</a></code> mode, no subsidiary
guard checking will be done.<p>
Notice that by treating functions in <code>:</code><code><a href="PROGRAM.html">program</a></code> mode like functions
whose guards have been verified, we are using raw lisp to compute
their values when their guards are met. We do not check guards any
further once raw lisp is invoked. This can lead to hard lisp errors
if the guards are not appropriate, as illustrated below.
<pre>
ACL2 >:program
ACL2 p>(defun foo (x)
(declare (xargs :guard t))
(cons 1 (cdr x)))<p>
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.02 seconds (prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.02)
FOO
ACL2 p>(foo 3)<p>
Error: 3 is not of type LIST.
Fast links are on: do (use-fast-links nil) for debugging
Error signalled by CDR.
Broken at COND. Type :H for Help.
ACL2>>
</pre>
See <a href="DEFUN-MODE-CAVEAT.html">defun-mode-caveat</a>.<p>
However, here is a way to get ACL2 to do run-time guard checking for
user-defined <code>:</code><code><a href="PROGRAM.html">program</a></code> mode functions. With this method, ACL2 will
evaluate calls of user-defined <code>:program</code> mode functions in a manner
that follows their ACL2 definitions. Simply execute the following in the
ACL2 loop to put ACL2 into a ``safe mode.''
<pre>
(f-put-global 'safe-mode t state)
</pre>
Let us revisit the example above, using safe mode. Notice that the guard of
<code><a href="CDR.html">cdr</a></code> is now being checked, because the executable counterpart of <code>foo</code>
is being called even though the <a href="GUARD.html">guard</a> is <code>t</code>.
<pre>
ACL2 !>(f-put-global 'safe-mode t state)
<state>
ACL2 !>:program
ACL2 p!>(defun foo (x)
(declare (xargs :guard t))
(cons 1 (cdr x)))<p>
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 p!>(foo 3)<p>
ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CDR 3). You may be able to see a trace of calls leading up to
this violation by executing (wet <form>), where <form> is the form
you submitted to the ACL2 loop. See :DOC wet for how to get an error
backtrace.<p>
ACL2 p!>(wet (foo 3))<p>
<p>
ACL2 Error in WITH-ERROR-TRACE: The guard for the function symbol
CDR, which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments
in the call (CDR 3). (Backtrace is below.)<p>
1> (ACL2_*1*_ACL2::FOO 3)<p>
ACL2 p!>
</pre>
If we go back into ``unsafe'' mode, then we once again see a raw Lisp error,
as we now illustrate.
<pre>
ACL2 p!>(f-put-global 'safe-mode nil state)
<state>
ACL2 p!>(foo 3)<p>
Error: 3 is not of type LIST.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by CDR.
Broken at COND. Type :H for Help.
ACL2>>
</pre>
<p>
<em>Guards and evaluation V: efficiency issues</em><p>
We have seen that by verifying the guards for a <code>:</code><code><a href="LOGIC.html">logic</a></code> function, we
arrange that raw lisp is used for evaluation of calls of such
functions when the arguments satisfy its guard.<p>
This has several apparent advantages over the checking of guards as
we go. First, the savings is magnified as your system of functions
gets deeper: the guard is checked upon the top-level entry to your
system and then raw Common Lisp does all the computing. Second, if
the raw Common Lisp is compiled, enormous speed-ups are possible.
Third, if your Common Lisp or its compiler does such optimizations
as <code>tail-recursion</code> removal, raw Common Lisp may be able to
compute your functions on input much ``bigger'' than ACL2 can.<p>
The first of these advantages is quite important if you have
complicated guards. However, the other two advantages are probably
not very important, as we now explain.<p>
When a function is defined in <code>:</code><code><a href="LOGIC.html">logic</a></code> mode, its <code><a href="DEFUN.html">defun</a></code> is
executed in raw Common Lisp. (We might call this the ``primary''
raw lisp definition of the function.) However, a corresponding
``logic definition'' is also executed. The ``logic definition'' is
a <code><a href="DEFUN.html">defun</a></code> in raw lisp that checks guards at runtime and escapes to
the primary raw lisp definition if the guard holds of the arguments
and the function has already had its guards verified. Otherwise the
logic definition executes the body of the function by calling the
logic definitions of each subroutine. Now it is true that
<a href="COMPILATION.html">compilation</a> generally speeds up execution enormously. However, the
<code>:</code><code><a href="COMP.html">comp</a></code> command (see <a href="COMP.html">comp</a>) compiles both of the raw lisp
definitions associated with a <code>:</code><code><a href="LOGIC.html">logic</a></code> function. Also, we have
attempted to arrange that for every tail recursion removal done on
the actual <code><a href="DEFUN.html">defun</a></code>, a corresponding tail recursion removal is done
on the ``logic definition.''<p>
We believe that in most cases, the logic definition executes almost
as fast as the primary raw lisp definition, at least if the
evaluation of the guards is fast. So, the main advantage of guard
verification is probably that it lets you know that the function may
be executed safely in raw lisp, returning the value predicted by the
ACL2 logic, whenever its arguments satisfy its guard. We envision
the development of systems of applicative lisp functions that have
been developed and reasoned about using ACL2 but which are intended
for evaluation in raw Common Lisp (perhaps with only a small
``core'' of ACL2 loaded), so this advantage of guard verification is
important.<p>
Nevertheless, guard verification might be important for optimal
efficiency when the functions make use of type declarations. For
example, at this writing, the GCL implementation of Common Lisp can
often take great advantage of <code><a href="DECLARE.html">declare</a></code> forms that assign small
integer types to formal parameters.<p>
To continue the discussion of guards,
see <a href="GUARDS-FOR-SPECIFICATION.html">guards-for-specification</a> to read about the use of guards as
a specification device.
<br><br><br><a href="acl2-doc.html"><img src="llogo.gif"></a> <a href="acl2-doc-index.html"><img src="index.gif"></a>
</body>
</html>
|