SET-GUARD-CHECKING.html -- ACL2 Version 6.3

## SET-GUARD-CHECKING

control checking guards during execution of top-level forms

    Major Section:  SWITCHES-PARAMETERS-AND-MODES

Detailed comments about the arguments of this function may be found elsewhere: see guard-evaluation-table. Here we provide an introduction to the use of `set-guard-checking`.

New users are encouraged to execute one of the following forms in order to avoid evaluation errors due to guards:

    (set-guard-checking :none)
    (set-guard-checking nil)

The former avoids all guard-checking on user-defined functions and should generally work fine for new users, the only drawback being efficiency loss on compute-intensive problems. All settings other than `:none` check guards, but a value of `nil` allows evaluation to continue in the logic when guards fail (avoiding the raw Lisp definition in that case).

You may put one of the above forms in the `"acl2-customization.lsp"` file in your current directory (see cbd) or your home directory; see acl2-customization.

Note that guards are not part of the ACL2 logic, and hence new users can completely ignore the notion of guard (and the rest of this documentation section after this paragraph!). For example, `(car 3)` and `nil` can be proved equal in the ACL2 logic, as follows, even though the guard on `car` requires its first argument to be a `cons` pair or `nil`.

    (thm (equal (car 3) nil))

Moreover, unless your functions or top-level forms call built-in ACL2 functions that are defined in `:``program` mode, the following property will hold.

> Evaluation of `(set-guard-checking :none)` will allow evaluation of forms such as `(car 3)` to take place without error in the top level loop, not only when proving theorems.

If you feel bold, then you may wish to read the rest of this documentation topic; also see guard.

See guard-evaluation-table for a succinct table, with associated discussion, that covers in detail the material presented in the rest of the present topic.

The top-level ACL2 loop has a variable which controls which sense of execution is provided. To turn ``guard checking on,'' by which we mean that guards are checked at runtime, execute the top-level form `:set-guard-checking t`. To allow guard violations, do `:set-guard-checking nil`, or do `:set-guard-checking :none` to turn off all guard-checking, so that raw Lisp definitions of user-defined functions are avoided unless their guard is `t`. The status of guard-checking is reflected in the prompt.

    ACL2 !>

means guard checking is on and

    ACL2 >

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

    ACL2 !>(car 'abc)

will signal an error, while

    ACL2 >(car 'abc)

will return `nil`.

We will return at the end of this documentation topic to discuss two other values, `:all` and `:nowarn`, for `:set-guard-checking`. We also note that evaluation of built-in `:program` mode functions always takes place in raw Lisp.

Whether guards are checked during evaluation is independent of the `default-defun-mode`. We note this simply because it is easy to confuse ```:``program` mode'' with ``evaluation in Common Lisp'' and thus with ``guard checking on;'' and it is easy to confuse ```:``logic` mode'' with ``evaluation in the logic'' and with ``guard checking off.'' But the `default-defun-mode` determines whether newly submitted definitions introduce programs or add logical axioms. That mode is independent of whether evaluation checks guards or not. You can operate in `:``logic` mode with runtime guard checking on or off. Analogously, you can operate in `:``program` mode with runtime guard checking on or off.

For further discussion on evaluation and guards see guards-and-evaluation, in particular the exception for safe-mode in the ``Aside'' there. See guard for a general discussion of guards.

Now we fulfill our promise above to discuss two other values for `:set-guard-checking`:

    :set-guard-checking :nowarn
    :set-guard-checking :all

The meaning of these values is perhaps best described by the following example provided by David Rager.

    ACL2 !>(defun my-test (expr)
             (declare (xargs :guard (true-listp expr)
                             :verify-guards nil))
             (if (atom expr)
                 expr
               (cons (my-test (car expr))
                     (my-test (cdr expr)))))

    The admission of MY-TEST is trivial, using the relation O< (which is
    known to be well-founded on the domain recognized by O-P) and the measure
    (ACL2-COUNT EXPR).  We could deduce no constraints on the type of MY-
    TEST.  However, in normalizing the definition we used primitive type
    reasoning.

    Summary
    Form:  ( DEFUN MY-TEST ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     MY-TEST
    ACL2 !>(my-test '(a b c))

    ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking will be inhibited
    on recursive calls of the executable counterpart (i.e., in the ACL2
    logic) of MY-TEST.  To check guards on all recursive calls:
      (set-guard-checking :all)
    To leave behavior unchanged except for inhibiting this message:
      (set-guard-checking :nowarn)

    (A B C)
    ACL2 !>

If you think about evaluation of `(my-test '(a b c))`, you will see that it leads to the recursive call `(my-test 'a)`, which one might expect to cause a guard violation since the symbol `a` is not a `true-listp`. However, as the warning above explains, we do not by default check guards on recursive calls. The reason is efficiency -- imagine a simple definition with a guard that is slow to evaluate. The values `:nowarn` and `:all` for `:set-guard-checking` have been introduced as ways of dealing with the above warning. The value `:nowarn` simply turns off the warning above. The value `:all` causes all guards to be checked, even on recursive calls and even on all calls of non-built-in `:``program` mode functions -- unless, of course, a call is made of a function whose guard has been verified (see verify-guards), where the arguments satisfy the guard, in which case the corresponding call is made in raw Lisp without subsidiary guard-checking. We still say that ``guard-checking is on'' after `:set-guard-checking` is invoked with values `t`, `:nowarn`, and `:all`, otherwise (after value `nil`) we say ``guard-checking is off.

For technical reasons, `:all` does not have its advertised effect in the case of built-in `:``program`-mode functions. If you are interested in this technical detail, see the comment ``In the boot-strap world...'' in source function `oneify-cltl-code`.

We conclude with a remark about the use of `:set-guard-checking` for experimenting with ACL2 as a logic or as a programming language. If one views ACL2 as a logic, one may wish to use `:set-guard-checking :none`, while if instead one views ACL2 as a functional programming language, one may wish to use `:set-guard-checking :all`. The following transcript illustrates this distinction by way of example. Specifically, `(car 3)` is equal to `nil` in the ACL2 logic, but may be viewed as a programming error. The default of `:set-guard-checking t` is problematic for learning ACL2 using `:``program` mode functions, since one can get raw Lisp errors. In the example below, the raw Lisp error occurs because `foo` implicitly has a guard of `t`, hence `(foo 3)` is evaluated in raw Lisp, which leads to a raw Lisp call of c[(car 3)].

    ACL2 !>(defun foo (x)
             (declare (xargs :mode :program))
             (car x))

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: NIL
    Warnings:  None
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     FOO
    ACL2 !>(foo 3)
    Error: Attempt to take the car of 3 which is not listp.
      [condition type: TYPE-ERROR]

    Restart actions (select using :continue):
     0: Abort entirely from this (lisp) process.
    [Current process: Initial Lisp Listener]
    [1] ACL2(1): [RAW LISP] :pop
    ACL2 !>:set-guard-checking :none

    Turning off guard checking entirely.  To allow execution in raw Lisp
    for functions with guards other than T, while continuing to mask guard
    violations, :SET-GUARD-CHECKING NIL.  See :DOC set-guard-checking.

    ACL2 >(foo 3)
    NIL
    ACL2 >:set-guard-checking :all

    Turning guard checking on, value :ALL.

    ACL2 !>(foo 3)

    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 trace for a useful debugging utility.  See :DOC
    set-guard-checking for information about suppressing this check with
    (set-guard-checking :none), as recommended for new users.

    ACL2 !>