• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
      • Theories
      • Rule-classes
      • Proof-builder
      • Recursion-and-induction
      • Hons-and-memoization
      • Events
      • Parallelism
      • History
      • Programming
        • Defun
        • Declare
        • System-utilities
        • Stobj
        • State
        • Mutual-recursion
        • Memoize
        • Mbe
        • Io
        • Defpkg
        • Apply$
        • Loop$
        • Programming-with-state
        • Arrays
        • Characters
        • Time$
        • Defmacro
        • Loop$-primer
        • Fast-alists
        • Defconst
        • Evaluation
        • Guard
          • Verify-guards
          • Mbe
          • Set-guard-checking
          • Ec-call
          • Print-gv
          • The
          • Guards-and-evaluation
          • Guard-debug
          • Set-check-invariant-risk
          • Guard-evaluation-table
          • Guard-evaluation-examples-log
          • Guard-example
            • Defthmg
            • Invariant-risk
            • With-guard-checking
            • Guard-miscellany
            • Guard-holders
            • Guard-formula-utilities
            • Set-verify-guards-eagerness
            • Guard-quick-reference
            • Set-register-invariant-risk
            • Guards-for-specification
            • Guard-evaluation-examples-script
            • Guard-introduction
            • Program-only
            • Non-exec
            • Set-guard-msg
            • Safe-mode
            • Set-print-gv-defaults
            • Guard-theorem-example
            • With-guard-checking-event
            • With-guard-checking-error-triple
            • Guard-checking-inhibited
            • Extra-info
          • Equality-variants
          • Compilation
          • Hons
          • ACL2-built-ins
          • Developers-guide
          • System-attachments
          • Advanced-features
          • Set-check-invariant-risk
          • Numbers
          • Efficiency
          • Irrelevant-formals
          • Introduction-to-programming-in-ACL2-for-those-who-know-lisp
          • Redefining-programs
          • Lists
          • Invariant-risk
          • Errors
          • Defabbrev
          • Conses
          • Alists
          • Set-register-invariant-risk
          • Strings
          • Program-wrapper
          • Get-internal-time
          • Basics
          • Packages
          • Oracle-eval
          • Defmacro-untouchable
          • <<
          • Primitive
          • Revert-world
          • Unmemoize
          • Set-duplicate-keys-action
          • Symbols
          • Def-list-constructor
          • Easy-simplify-term
          • Defiteration
          • Fake-oracle-eval
          • Defopen
          • Sleep
        • Operational-semantics
        • Real
        • Start-here
        • Debugging
        • Miscellaneous
        • Output-controls
        • Macros
        • Interfacing-tools
      • Interfacing-tools
      • Hardware-verification
      • Software-verification
      • Math
      • Testing-utilities
    • Tutorial5-miscellaneous-examples
    • Guard

    Guard-example

    A brief transcript illustrating guards in ACL2

    This note addresses the question: what is the use of guards in ACL2? Although we recommend that beginners try to avoid guards for a while, we hope that the summary here is reasonably self-contained and will provide a helpful introduction to guards in ACL2. For a more systematic discussion, see guard. For a summary of that topic, see guard-quick-reference.

    Before we get into the issue of guards, let us note that there are two important “modes”:

    defun-mode — “Does this defun add an axiom (‘logic mode’) or not (`:program mode')?” (See defun-mode.) Only logic mode functions can have their “guards verified” via mechanized proof; see verify-guards.

    set-guard-checking — “Should runtime guard violations signal an error (:all, and usually with t or :nowarn) or go undetected (nil, :none)? The question relates to the use of Common Lisp to evaluate expressions; see set-guard-checking.

    Examples of prompts

    Here are some examples of the relation between the ACL2 prompt and the “modes” discussed above. Also see default-print-prompt. The first examples all have ld-skip-proofsp equal to nil; that is, proofs are not skipped.

    ACL2 !>    ; logic mode with guard checking on
    ACL2 >     ; logic mode with guard checking off
    ACL2 p!>   ; program mode with guard checking on
    ACL2 p>    ; program mode with guard checking off

    Here are some examples with default-defun-mode equal to :logic.

    ACL2 >     ; guard checking off, ld-skip-proofsp nil
    ACL2 s>    ; guard checking off, ld-skip-proofsp t
    ACL2 !>    ; guard checking on, ld-skip-proofsp nil
    ACL2 !s>   ; guard checking on, ld-skip-proofsp t

    Sample session

    ACL2 !>(+ 'abc 3)
    
    
    ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
    (BINARY-+ X Y), which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)), is
    violated by the arguments in the call (BINARY-+ 'ABC 3).
    See :DOC set-guard-checking for information about suppressing this
    check with (set-guard-checking :none), as recommended for new users.
    To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
    
    ACL2 !>:set-guard-checking nil
    [[.. output elided ..]]
    ACL2 >(+ 'abc 3)
    3
    ACL2 >(< 'abc 3)
    T
    ACL2 >(< 3 'abc)
    NIL
    ACL2 >(< -3 'abc)
    T
    ACL2 >:set-guard-checking t
    
    Turning guard checking on, value T.
    
    ACL2 !>(defun sum-list (x)
            (declare (xargs :guard (integer-listp x)
                            :verify-guards nil))
            (cond ((endp x) 0)
                  (t (+ (car x) (sum-list (cdr x))))))
    
    The admission of SUM-LIST 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 X).
    We observe that the type of SUM-LIST is described by the
    theorem (ACL2-NUMBERP (SUM-LIST X)).  We used primitive type
    reasoning.
    
    Summary
    Form:  ( DEFUN SUM-LIST ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.03)
     SUM-LIST
    ACL2 !>(sum-list '(1 2 3))
    
    ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking will be inhibited
    for some recursive calls, including SUM-LIST; see :DOC guard-checking-
    inhibited.
    
    6
    ACL2 !>(sum-list '(1 2 abc 3))
    
    
    ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
    (SUM-LIST X), which is (INTEGER-LISTP X), is violated by the arguments
    in the call (SUM-LIST '(1 2 ABC 3)).
    See :DOC set-guard-checking for information about suppressing this
    check with (set-guard-checking :none), as recommended for new users.
    To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
    
    ACL2 !>:set-guard-checking nil
    [[.. output elided ..]]
    ACL2 >(sum-list '(1 2 abc 3))
    6
    ACL2 >(defthm sum-list-append
           (equal (sum-list (append a b))
                  (+ (sum-list a) (sum-list b))))
    
    *1 (the initial Goal, a key checkpoint) is pushed for proof by induction.
    
    Perhaps we can prove *1 by induction.  Three induction schemes are
    suggested by this conjecture.  Subsumption reduces that number to two.
    However, one of these is flawed and so we are left with one viable
    candidate.
    
    [[.. output elided ..]]
    
    *1 is COMPLETED!
    Thus key checkpoint Goal is COMPLETED!
    
    Q.E.D.
    
    Summary
    Form:  ( DEFTHM SUM-LIST-APPEND ...)
    Rules: ((:DEFINITION BINARY-APPEND)
            (:DEFINITION ENDP)
    [[.. output elided ..]]
            (:TYPE-PRESCRIPTION SUM-LIST))
    
    Time:  0.01 seconds (prove: 0.01, print: 0.00, other: 0.00)
    Prover steps counted:  470
     SUM-LIST-APPEND

    Guard verification for functions

    See declare, and xargs, and verify-guards for related background, though we intend what follows to be self-explanatory.

          Declare Form                        Guards Verified?
    
      (declare (xargs :mode :program ...))          no
      (declare (xargs :guard g))                    yes
      (declare (xargs :guard g :verify-guards nil)) no
      (declare (xargs ...<no :guard>...))           no
    
    ACL2 >:pe sum-list
     L         1  (DEFUN SUM-LIST (X)
                    (DECLARE (XARGS :GUARD (INTEGER-LISTP X)
                                    :VERIFY-GUARDS NIL))
                    (COND ((ENDP X) 0)
                          (T (+ (CAR X) (SUM-LIST (CDR X))))))
    ACL2 >(verify-guards sum-list)
    
    Computing the guard conjecture for SUM-LIST....
    
    The non-trivial part of the guard conjecture for SUM-LIST, given the
    
    [[.. output elided ..]]
    
    Q.E.D.
    
    That completes the proof of the guard theorem for SUM-LIST.  SUM-LIST
    is compliant with Common Lisp.
    
    Summary
    Form:  ( VERIFY-GUARDS SUM-LIST)
    Rules: ((:DEFINITION ENDP)
    [[.. output elided ..]]
            (:TYPE-PRESCRIPTION SUM-LIST))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    Prover steps counted:  115
     SUM-LIST
    ACL2 >:pe sum-list
     LV        1  (DEFUN SUM-LIST (X)
                    (DECLARE (XARGS :GUARD (INTEGER-LISTP X)
                                    :VERIFY-GUARDS NIL))
                    (COND ((ENDP X) 0)
                          (T (+ (CAR X) (SUM-LIST (CDR X))))))
    ACL2 >:set-guard-checking t
    
    Turning guard checking on, value T.
    
    ACL2 !>(sum-list '(1 2 abc 3))
    
    
    ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
    (SUM-LIST X), which is (INTEGER-LISTP X), is violated by the arguments
    in the call (SUM-LIST '(1 2 ABC 3)).
    See :DOC set-guard-checking for information about suppressing this
    check with (set-guard-checking :none), as recommended for new users.
    To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
    
    ACL2 !>:set-guard-checking nil
    [[.. output elided ..]]
    ACL2 >(sum-list '(1 2 abc 3))
    6
    ACL2 >

    We continue this demo by tracing sum-list. (See trace$.) The calls shown below of ACL2_*1*_ACL2::SUM-LIST are calls of the logical version, or executable-counterpart, of sum-list; also see evaluation. Note that the guard-checking value is still nil. So the logical version of sum-list calls the Common Lisp sum-list function when the guard of “list of integers” is true of its input, i.e., its input satisfies integer-listp; but otherwise, evaluation continues using its executable-counterpart.

    ACL2 >(trace$ sum-list)
     ((SUM-LIST))
    ACL2 >(sum-list '(1 2 abc 3))
    1> (ACL2_*1*_ACL2::SUM-LIST (1 2 ABC 3))
      2> (ACL2_*1*_ACL2::SUM-LIST (2 ABC 3))
        3> (ACL2_*1*_ACL2::SUM-LIST (ABC 3))
          4> (ACL2_*1*_ACL2::SUM-LIST (3))
            5> (SUM-LIST (3))
              6> (SUM-LIST NIL)
              <6 (SUM-LIST 0)
            <5 (SUM-LIST 3)
          <4 (ACL2_*1*_ACL2::SUM-LIST 3)
        <3 (ACL2_*1*_ACL2::SUM-LIST 3)
      <2 (ACL2_*1*_ACL2::SUM-LIST 5)
    <1 (ACL2_*1*_ACL2::SUM-LIST 6)
    6
    ACL2 >

    Guard verification for theorems

    For a theorem to be guard-verified, its statement should be executable without error in Common Lisp. The following is thus not guard-verifiable, since its evaluation can cause an error if A and B are not both lists of numbers.

    ACL2 >:pe sum-list-append
               2  (DEFTHM SUM-LIST-APPEND
                    (EQUAL (SUM-LIST (APPEND A B))
                           (+ (SUM-LIST A) (SUM-LIST B))))
    ACL2 >(verify-guards sum-list-append)
    
    Computing the guard conjecture for SUM-LIST-APPEND....
    
    The non-trivial part of the guard conjecture for
    SUM-LIST-APPEND, given the :type-prescription rule SUM-LIST,
    is
    
    Goal
    (AND (TRUE-LISTP A)
         (INTEGER-LISTP A)
         (INTEGER-LISTP (APPEND A B))
         (INTEGER-LISTP B)).
    
    ******** FAILED ********
    ACL2 >

    Perhaps surprisingly, a defthm event with statement

    (implies (and (integer-listp a)
                  (integer-listp b))
             (equal (sum-list (append a b))
                    (+ (sum-list a) (sum-list b))))

    is still not guard-verifiable. The reason is that implies is a function, so its arguments are both always evaluated — in particular, its second argument is evaluated even if its first argument evaluates to nil. Here is a way to fix that problem.

    ACL2 >(defthm common-lisp-sum-list-append
             (if (and (integer-listp a)
                      (integer-listp b))
                 (equal (sum-list (append a b))
                        (+ (sum-list a) (sum-list b)))
                 t)
             :rule-classes nil)
    
    Q.E.D.
    
    Summary
    Form:  ( DEFTHM COMMON-LISP-SUM-LIST-APPEND ...)
    Rules: ((:REWRITE SUM-LIST-APPEND))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    Prover steps counted:  23
     COMMON-LISP-SUM-LIST-APPEND
    ACL2 >(verify-guards common-lisp-sum-list-append)
    
    Computing the guard conjecture for COMMON-LISP-SUM-LIST-APPEND....
    
    The non-trivial part of the guard conjecture for COMMON-LISP-SUM-LIST-APPEND,
    given the :forward-chaining rules ACL2-NUMBER-LISTP-FORWARD-TO-TRUE-LISTP,
    INTEGER-LISTP-FORWARD-TO-RATIONAL-LISTP and
    RATIONAL-LISTP-FORWARD-TO-ACL2-NUMBER-LISTP and the :type-prescription
    rules ACL2-NUMBER-LISTP, INTEGER-LISTP, RATIONAL-LISTP and SUM-LIST,
    is
    
    Goal
    (IMPLIES (AND (INTEGER-LISTP A)
                  (INTEGER-LISTP B))
             (INTEGER-LISTP (APPEND A B))).
    
    [[.. output elided ..]]
    
    Q.E.D.
    
    That completes the proof of the guard theorem for
    COMMON-LISP-SUM-LIST-APPEND.  COMMON-LISP-SUM-LIST-APPEND is compliant
    with Common Lisp.
    
    Summary
    Form:  ( VERIFY-GUARDS COMMON-LISP-SUM-LIST-APPEND)
    Rules: ((:DEFINITION BINARY-APPEND)
    [[.. output elided ..]]
            (:TYPE-PRESCRIPTION SUM-LIST))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    Prover steps counted:  565
     COMMON-LISP-SUM-LIST-APPEND
    ACL2 >

    Guard verification fails when the theorem is for “code” that cannot even be parsed (or “translated”; see term) as executable code.

    ACL2 >(defthm foo (consp (mv x y)))
    
    Q.E.D.
    
    The storage of FOO depends upon primitive type reasoning.
    
    Summary
    Form:  ( DEFTHM FOO ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     FOO
    ACL2 >(verify-guards foo)
    
    
    ACL2 Error in ( VERIFY-GUARDS FOO):  The guards for FOO cannot be verified
    because its formula has the wrong syntactic form for evaluation, perhaps
    due to multiple-value or stobj restrictions.  See :DOC verify-guards.
    
    
    Summary
    Form:  ( VERIFY-GUARDS FOO)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    
    ACL2 Error [Failure] in ( VERIFY-GUARDS FOO):  See :DOC failure.
    
    ******** FAILED ********
    ACL2 >