Major Section: GUARD
The discussion of guards concludes here with a few miscellaneous
remarks. (Presumably you found this documentation by following a link;
see guards-for-specification.) For further information related to guards
other than what you find under ``guard,'' see any of the following
documentation topics: guard-example, set-verify-guards-eagerness
,
set-guard-checking
, verify-guards
, and (for a discussion of
keyword :SPLIT-TYPES
) xargs
.
Defun
can be made to try to verify the guards on a function. This is
controlled by the ``defun-mode'' of the defun
; see defun-mode.
The defun-mode is either as specified with the :mode
xarg
of the
defun
or else defaults to the default defun-mode.
See default-defun-mode. If the defun-mode of the defun
is
:
logic
and either a guard is specified explicitly or
:
verify-guards
t
is specified in the xargs
, then we
attempt to verify the guards of the function. Otherwise we do not.
(But see set-verify-guards-eagerness for how to modify this behavior.)
It is sometimes impossible for the system to verify the guards of a recursive
function at definition time. For example, the guard conjectures might
require the invention and proof of some inductively derived property of the
function (as often happens when the value of a recursive call is fed to a
guarded subroutine). So sometimes it is necessary to define the function
using :verify-guards nil
then to state and prove key theorems about the
function, and only then have the system attempt guard verification.
Post-defun
guard verification is achieved via the event
verify-guards
. See verify-guards.
It should be emphasized that guard verification affects only two things: how fast ACL2 can evaluate the function and whether the function is executed correctly by raw Common Lisp, without guard violations. Since ACL2 does not use the raw Common Lisp definition of a function to evaluate its calls unless that function's guards have been verified, the latter effect is felt only if you run functions in raw Common Lisp rather than via ACL2's command loop.
Guard verification does not otherwise affect the theorem prover or the semantics of a definition. If you are not planning on running your function on ``big'' inputs and you don't care if your function runs correctly in raw Common Lisp (e.g., you have formalized some abstract mathematical property and just happened to use ACL2 as your language), there is no need to suffer through guard verification. Often users start by not doing guard verification and address that problem later. Sometimes you are driven to it, even in mathematical projects, because you find that you want to run your functions particularly fast or in raw Common Lisp.
If certify-book
is used to compile a file, and the file contains
functions with unverified guard conjectures, then you will be warned that the
compiled file cannot be loaded into raw Common Lisp with the expectation that
the functions will run correctly. This is just the same point we have been
making: ACL2 and Common Lisp agree only on the restricted domains specified
by our guards. When guards are violated, Common Lisp can do anything. When
you call a compiled function on arguments violating its guards, the chances
are only increased that Common Lisp will go berserk, because compiled
functions generally check fewer things at runtime and tend to be more fragile
than interpreted ones.
Finally, we note that ACL2 collects up guards from declare
forms
in order of appearance. So for example, the declare
form
(declare (xargs :guard (foo x)) (type string x)will generate the guard
(and (foo x) (stringp x))
, while the form
(declare (type string x) (xargs :guard (foo x))will generate the guard
(and (stringp x) (foo x))
. The only exception to
this rule is the case that :guard
and :stobjs
are specified in the
same xargs
form, in which case the :stobjs
form will be treated as
through it comes before the :guard
form.